home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1991, 1992 Silicon Graphics, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and
- * its documentation for any purpose is hereby granted without fee, provided
- * that the name of Silicon Graphics may not be used in any advertising or
- * publicity relating to the software without the specific, prior written
- * permission of Silicon Graphics.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
- * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
- * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE
- * POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
- /*
- * Copyright (C) 1990,91,92 Silicon Graphics, Inc.
- *
- *
- _______________________________________________________________________
- ______________ S I L I C O N G R A P H I C S I N C . ____________
- |
- | $Revision: 1.1010 $
- |
- | Classes : SoSceneViewer
- |
- | Author(s) : Thad Beier, David Mott, Alain Dumesny, Paul Isaacs,
- | Rikk Carey, Dave Immel
- |
- ______________ S I L I C O N G R A P H I C S I N C . ____________
- _______________________________________________________________________
- */
-
- #include "Common.h"
- #include <stdlib.h>
- #include <getopt.h>
- #include <string.h>
- #include <stdio.h>
- #include <time.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <net/if.h>
- #include <net/soioctl.h>
- #include <arpa/inet.h>
- #include "multicast.h"
- #include <unistd.h> // for access()
- #include <sys/types.h>
- #include <sys/stat.h>
-
- #include <X11/StringDefs.h>
- #include <X11/Intrinsic.h>
- #include <X11/Xatom.h>
-
- #include <Xm/Xm.h>
- #include <Xm/BulletinB.h>
- #include <Xm/CascadeB.h>
- #include <Xm/CascadeBG.h>
- #include <Xm/FileSB.h>
- #include <Xm/Form.h>
- #include <Xm/Label.h>
- #include <Xm/FileSB.h>
- #include <Xm/PushB.h>
- #include <Xm/PushBG.h>
- #include <Xm/SeparatoG.h>
- #include <Xm/Text.h>
- #include <Xm/ToggleB.h>
- #include <Xm/ToggleBG.h>
-
- #include <Inventor/So.h>
- #include <Inventor/SoBaseKit.h>
- #include <Inventor/SoXt.h>
- #include <Inventor/SoXtColorEditor.h>
- #include <Inventor/SoBoxHighlight.h>
- #include <Inventor/SoLineHighlight.h>
- #include <Inventor/SoXtClipboard.h>
- #include <Inventor/SoXtDirectionalLightEditor.h>
- #include <Inventor/SoXtFileBrowser.h>
- #include <Inventor/SoXtMaterialEditor.h>
- #include <Inventor/SoXtPrintDialog.h>
- #include <Inventor/SoSelection.h>
- #include <Inventor/SoXtTransformSliderSet.h>
- #include <Inventor/SoXtResource.h>
- #include <Inventor/SoSensor.h>
- #include <Inventor/actions/SoGetBoundingBoxAction.h>
- #include <Inventor/actions/SoGetMatrixAction.h>
- #include <Inventor/nodes/SoSwitch.h>
- #include <Inventor/nodes/SoLight.h>
- #include <Inventor/nodes/SoDirectionalLight.h>
- #include <Inventor/nodes/SoPointLight.h>
- #include <Inventor/nodes/SoSpotLight.h>
- #include <Inventor/manips/SoDragPointManip.h>
- #include <Inventor/manips/SoHandleBoxManip.h>
- #include <Inventor/manips/SoJackManip.h>
- #include <Inventor/manips/SoTrackballManip.h>
- #include <Inventor/manips/SoTransformBoxManip.h>
- #include <Inventor/manips/SoDirectionalLightManip.h>
- #include <Inventor/manips/SoPointLightManip.h>
- #include <Inventor/manips/SoSpotLightManip.h>
- #include <Inventor/viewers/SoXtExaminerViewer.h>
- #include <Inventor/viewers/SoXtWalkViewer.h>
- #include <Inventor/viewers/SoXtFlyViewer.h>
- #include <Inventor/viewers/SoXtPlaneViewer.h>
- #include <Inventor/viewers/SoXtViewer.h>
-
- #include "SoSceneViewer.h"
- #include "SoSceneMenu.h"
- #include "SvManipList.h"
-
- #include <gl/gl.h>
- #include <malloc.h>
- #ifdef DEBUG
- #include <assert.h>
- #endif
-
- //
- // Macros and constants
- //
-
- // toggle button macros
- #define TOGGLE_ON(BUTTON) \
- XmToggleButtonSetState((Widget) BUTTON, TRUE, FALSE)
- #define TOGGLE_OFF(BUTTON) \
- XmToggleButtonSetState((Widget) BUTTON, FALSE, FALSE)
-
- #define FOG_FUDGE 1.6
- #define SV_NUM_LIGHTS 6
-
- #define SWITCH_LIGHT_OFF(SWITCH) (SWITCH)->whichChild.setValue(SO_SWITCH_NONE)
- #define SWITCH_LIGHT_ON(SWITCH) (SWITCH)->whichChild.setValue(SO_SWITCH_ALL)
- #define IS_LIGHT_ON(SWITCH) ((SWITCH)->whichChild.getValue() == SO_SWITCH_ALL)
-
- #define SV_ENV_LABEL "SoSceneViewer Environment v3.0"
-
- //
- // Structs
- //
-
- struct SoSceneViewerData {
- int id;
- SoSceneViewer *classPt;
- Widget widget;
- };
-
- struct SvLightData {
- SoSceneViewer *classPt;
- SoSwitch *lightSwitch;
- SoLight *light;
- SoLight::Type type;
- char *name;
- SoXtColorEditor *colorEditor;
- SoDragManip *manip;
- Widget cascadeWidget;
- Widget submenuWidget;
- Widget onOffWidget;
- Widget iconWidget;
- Widget editColorWidget;
- Widget removeWidget;
- };
-
- // added by smf
- extern SoSceneViewer *mysv;
- extern SoDataSensor *envirosensor;
- extern SoTimerSensor *timersensor;
- extern void printScreen(SoSceneViewer *);
- void mystartcallback(void *,SoXtViewer *);
- void mystopcallback(void *,SoXtViewer *);
- int flag;
- int timerflag=1;
- int rotflag;
- struct stat buf;
- time_t lasttime=-1;
- char mybuff[1000];
- char temp[1000];
- extern struct sockaddr_in inaddr,outaddr;
- extern int inaddrlen,outaddrlen, infd, outfd, cnt, i;
- extern struct ip_mreq mreq;
- extern char *group ;
- extern u_short port ;
- extern u_char ttl ;
- extern int send_mode ;
- extern int iflag ;
- extern char *interface;
- extern struct in_addr ifaddr;
- extern struct in_addr grpaddr;
-
-
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Constructor for the SoSceneViewer.
- // Creates the Topbar menu
- //
- // Use: public
-
- SoSceneViewer::SoSceneViewer(SoSelection *inputGraph, const char *envFile)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- Arg args[1];
- int i;
-
- SoXtComponent::setSize( SbVec2s(520, 480) );
-
- // selection is the users scene graph.
- selection = inputGraph;
- createLightsCameraEnvironment();
-
- // the scene viewer supplies its own camera and lights.
- // in fact, we remove any cameras that might be in the users graph.
- sceneGraph = new SoSeparator();
- sceneGraph->ref(); // must ref it
- sceneGraph->addChild(lightsCameraEnvironment);
- sceneGraph->addChild(selection);
- #ifndef EXPLORER
- removeCameras(selection);
- #endif
-
- //
- // Widget and menu variables
- //
- mgrWidget = NULL;
- showMenuFlag = TRUE;
- menuWidget = NULL;
- menuItems = new SoSceneViewerData[SV_MENU_NUM];
- for (i=0; i<SV_MENU_NUM; i++) {
- menuItems[i].id = i;
- menuItems[i].classPt = this;
- menuItems[i].widget = NULL;
- }
-
- //
- // File
- //
- fileName = NULL;
- fileDialog = NULL;
- browser = NULL;
- printDialog = NULL;
- // check which file browser to use
- char *browserName = getenv("SO_FILE_BROWSER");
- if (browserName != NULL && strcasecmp(browserName, "showcase") == 0)
- useShowcaseBrowser = TRUE;
- else
- useShowcaseBrowser = FALSE;
-
- //
- // Edit
- //
- highlightColorEditor = NULL;
-
- //
- // Viewing
- //
- // Allocate only one viewer at a time. The other viewers will
- // be allocated as needed to increase speed and save memory.
- //
- for (i=0; i<4; i++)
- viewerList[i] = NULL;
- whichViewer = SV_VWR_EXAMINER;
- setTitle("SharedSV (Examiner) author: fine@detroit.sgi.com");
- currentViewer = viewerList[whichViewer] = new SoXtExaminerViewer;
- currentViewer->setSceneGraph(sceneGraph);
- // added by smf
- currentViewer->addStartCallback(mystartcallback,currentViewer);
- currentViewer->addFinishCallback(mystopcallback,currentViewer);
- // since we created the camera, do a view all and save this
- // as the starting point (don't want default camera values).
- viewAll();
- saveHomePosition();
-
- // fog
- fogFlag = FALSE;
- environment->fogType.setValue( SoEnvironment::NONE );
- environment->fogColor.setValue( getBackgroundColor() );
-
- antialiasingFlag = FALSE;
- backgroundColorEditor = NULL;
-
- //
- // Selection
- // These callbacks are used to update the SceneViewer state after
- // the current selection changes (e.g. attach/detach editors and manips).
- //
- selection->addObjectSelectedCallback( SoSceneViewer::selectionCallback, this );
- selection->addObjectDeselectedCallback( SoSceneViewer::deselectionCallback, this );
- lineHighlight = new SoLineHighlight;
- boxHighlight = new SoBoxHighlight;
-
- // default selection highlight style
- selection->setHighlightStyle(boxHighlight);
-
- //
- // Editors
- //
- ignoreCallback = FALSE;
- materialEditor = NULL;
- colorEditor = NULL;
- transformSliderSet = NULL;
-
- //
- // Manips
- //
- curManip = SV_NONE;
- curManipReplaces = TRUE;
- maniplist = new SvManipList;
-
- #ifdef EXPLORER
- //
- // User callback
- //
- userModeCB = NULL;
- userModedata = NULL;
- userModeFlag = FALSE;
- #endif /* EXPLORER */
-
- //
- // Lights
- //
- ambientColorEditor = NULL;
- headlightData = new SvLightData;
- headlightData->classPt = this;
- headlightData->name = strdup("Headlight");
- headlightData->type = SoLight::DIRECTIONAL;
- headlightData->colorEditor = NULL;
- headlightData->manip = NULL;
- headlightEditor = NULL;
- calculatedLightManipSize = FALSE;
-
- // do this after everything else has been set up
- if (envFile != NULL)
- readEnvFile(envFile);
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Destructor.
- //
- // Use: public
-
- SoSceneViewer::~SoSceneViewer()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- // detach and delete the viewers
- currentViewer->setSceneGraph(NULL);
- delete (SoXtExaminerViewer *) viewerList[SV_VWR_EXAMINER];
- delete (SoXtFlyViewer *) viewerList[SV_VWR_FLY];
- delete (SoXtWalkViewer *) viewerList[SV_VWR_WALK];
- delete (SoXtPlaneViewer *) viewerList[SV_VWR_PLANE];
-
- // delete menu items data
- delete [ /*SV_MENU_NUM*/ ] menuItems;
- delete headlightData;
- delete headlightEditor;
-
- delete browser;
- delete printDialog;
-
- // Editor components
- delete materialEditor;
- delete colorEditor;
- delete transformSliderSet;
- delete ambientColorEditor;
- delete backgroundColorEditor;
-
- // detach and delete the manips
- detachManipFromAll();
- delete maniplist;
-
- sceneGraph->unref();
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // New data is going to be coming into the viewer. Time to disconnect all
- // manipulators and picking, and wait for new information. Might as well go
- // into a viewing mode as well, this gets rid of the manipulators, and puts
- // the user in control of viewing when new data shows up.
- //
- // Use: public
- void
- SoSceneViewer::newData()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- selection->deselectAll();
- }
-
- #ifdef EXPLORER
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // This sets the user mode callack routine
- //
- // Use: public
- void
- SoSceneViewer::setUserModeEventCallback(SoXtRenderAreaEventCB *fcn)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- userModeCB = fcn;
- userModedata = currentViewer->getSceneGraph();
- if (userModeFlag)
- currentViewer->setEventCallback(userModeCB, userModedata);
- }
- #endif /* EXPLORER */
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // switches from the current viewer to the given viewer. The new
- // viewer will automatically be allocated if needed, and set to have
- // the same settings the current viewer has (drawing style, buffer
- // type, etc..).
- //
- // Use: private
- void
- SoSceneViewer::switchToViewer(SvEViewer newViewer)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- if (whichViewer == newViewer)
- return;
-
- // allocate the viewer if needed and set the window title.
- switch (newViewer) {
- case SV_VWR_EXAMINER:
- if ( viewerList[newViewer] == NULL )
- viewerList[newViewer] = new SoXtExaminerViewer;
- setTitle("SharedSV (Examiner) author: fine@detroit.sgi.com");
- break;
- case SV_VWR_FLY:
- if ( viewerList[newViewer] == NULL )
- viewerList[newViewer] = new SoXtFlyViewer;
- setTitle("SharedSV (Fly) author: fine@detroit.sgi.com");
- break;
- case SV_VWR_WALK:
- if ( viewerList[newViewer] == NULL )
- viewerList[newViewer] = new SoXtWalkViewer;
- setTitle("SharedSV (Walk) author: fine@detroit.sgi.com");
- break;
- case SV_VWR_PLANE:
- if ( viewerList[newViewer] == NULL )
- viewerList[newViewer] = new SoXtPlaneViewer;
- setTitle("SharedSV (Plane) author: fine@detroit.sgi.com");
- break;
- }
- SoXtFullViewer *newVwr = viewerList[newViewer];
-
- //
- // make sure the new viewer has all the same settings as
- // the current viewer.
- //
- // XtRenderArea methods
- newVwr->setBackgroundColor( currentViewer->getBackgroundColor() );
- newVwr->setTransparencyType( currentViewer->getTransparencyType() );
- SbBool smooth; int num;
- currentViewer->getAntialiasing(smooth, num);
- newVwr->setAntialiasing(smooth, num);
- newVwr->setClearBeforeRender( currentViewer->isClearBeforeRender() );
- newVwr->setAutoRedraw( currentViewer->isAutoRedraw() );
- // XtViewer methods
- newVwr->setHeadlight( currentViewer->isHeadlight() );
- newVwr->setDrawStyle( currentViewer->getDrawStyle() );
- newVwr->setBufferingType( currentViewer->getBufferingType() );
- newVwr->setViewing( currentViewer->isViewing() );
- newVwr->setAutoClipping( currentViewer->isAutoClipping() );
- newVwr->setGLRenderCaching( currentViewer->isGLRenderCaching() );
- newVwr->setSeekTime( currentViewer->getSeekTime() );
- // XtFullViewer methods
- newVwr->setDecoration( currentViewer->isDecoration() );
-
- #ifdef EXPLORER
- if (userModeFlag)
- newVwr->setEventCallback(userModeCB, userModedata);
- else
- newVwr->setEventCallback(NULL, NULL);
- #endif
-
- // build and layout the new viewer
- buildAndLayoutViewer(newVwr);
-
- // finally switch to the new viewer by attaching/showing the new
- // viewer, and detaching/hidding the old viewer (hide is done
- // last to reduce flicker).
- currentViewer->setSceneGraph(NULL);
- newVwr->setSceneGraph(sceneGraph);
- newVwr->show();
- currentViewer->hide();
- whichViewer = newViewer;
- currentViewer = newVwr;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Move up the picked path to the parent group.
- //
- // Use: public
-
- void
- SoSceneViewer::pickParent()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoPath *pickPath;
- int newIndex;
-
- pickPath = (*selection)[selection->getNumSelected() - 1]; // last guy or gal
- if(pickPath == NULL || pickPath->getLength() == 1)
- return;
-
- SoTypeList *priorities = selection->getSelectTypePriorityList();
- SoType checkType;
- int priority;
- SbBool gotOne;
-
- for ( priority = 0, gotOne = FALSE;
- gotOne == FALSE && priority < priorities->length();
- priority++ ) {
-
- checkType = (*priorities)[priority];
- if (checkType == SoNode::getClassTypeId()) {
- newIndex = pickPath->getLength() - 2; // parent of tail
- gotOne = TRUE;
- }
- else {
- for(newIndex = pickPath->getLength() - 2; newIndex >= 0; newIndex--) {
- if(pickPath->getNode(newIndex)->isOfType(checkType)) {
- gotOne = TRUE;
- break;
- }
- }
- }
- }
- if ( gotOne == FALSE )
- return;
-
- // cannot select the selection node (make sure we're not)
-
- if (pickPath->getNode(newIndex) == selection) {
- fprintf(stderr, "No more parents to pick (cannot pick above the selection node)\n");
- return;
- }
-
- pickPath->ref(); // need to ref it, because
- // selection->clear unref's it
- selection->deselectAll();
- pickPath->truncate(newIndex + 1); // Make path end at newIndex
- selection->select(pickPath); // add path back in
- pickPath->unref(); // now we can unref it, again
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Pick all group nodes and shapes under selection.
- //
- // Use: private
- void
- SoSceneViewer::pickAll()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- selection->deselectAll();
-
- #ifdef DEBUG
- assert(selection != NULL);
- #endif
-
- SoPathList myPaths;
-
- // Our callbacks on the selection's 'select' method may add
- // more children to the selection node (by making a trackball or handlebox)
- // Therefore, we must first determine the selections by storing
- // paths to them.
- // Following this, we call 'select' on each path, in turn.
-
- //
- // Create paths from the selection node to all of it's children
- // that are groups or shapes.
- //
- for (int i = 0; i < selection->getNumChildren(); i++) {
- SoNode *node = selection->getChild(i);
- if ((node->isOfType(SoGroup::getClassTypeId()) ||
- node->isOfType(SoShape::getClassTypeId())) &&
- (! node->isOfType(SoManipulator::getClassTypeId())))
-
- {
- SoPath *thisPath = new SoPath(selection);
- thisPath->append(i);
-
- myPaths.append( thisPath );
- }
- }
-
- //
- // Select each path in 'myPaths'
- //
- for (int j = 0; j < myPaths.length(); j++)
- selection->select(myPaths[j]);
- }
-
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // This routine first detaches manipulators from all selected objects,
- // then attaches a manipulator to all selected objects.
- //
- // Use: private
-
- void
- SoSceneViewer::replaceAllManips(
- SvEManipMode manipMode ) // Current manipulator
- //
- ////////////////////////////////////////////////////////////////////////
- {
- detachManipFromAll();
- attachManipToAll( manipMode );
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // This routine attaches a manipulator to all selected objects.
- //
- // Use: private
-
- void
- SoSceneViewer::attachManipToAll(
- SvEManipMode manipMode ) // Current manipulator
- //
- ////////////////////////////////////////////////////////////////////////
- {
- int i;
-
- for ( i = 0; i < selection->getNumSelected(); i++ ) {
- SoPath *p = (*selection)[i];
- attachManip( manipMode, p );
- }
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // This routine attaches and activates a manipulator.
- //
- // Use: private
-
- void
- SoSceneViewer::attachManip(
- SvEManipMode manipMode, // Current manipulator
- SoPath *selectedObject ) // Which selection to attach to
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoManipulator *theManip;
- SoPath *xfPath;
-
- //
- // Attach to a manipulator.
- //
-
- if ( manipMode == SV_NONE )
- return;
-
- xfPath = findTransformForAttach( selectedObject );
- xfPath->ref();
- theManip = NULL;
-
- switch( manipMode ) {
- case SV_TRACKBALL:
- theManip = new SoTrackballManip;
- break;
-
- case SV_HANDLEBOX:
- theManip = new SoHandleBoxManip;
- break;
-
- case SV_JACK:
- theManip = new SoJackManip;
- break;
-
- case SV_XFBOX:
- theManip = new SoTransformBoxManip;
- break;
-
- case SV_DRAGPOINT:
- theManip = new SoDragPointManip;
- break;
-
- case SV_NONE:
- return;
- }
-
- if ( theManip ) {
-
- theManip->ref();
-
- if ( !theManip->attach( xfPath ) ) {
- theManip->unref();
- #ifdef DEBUG
- fprintf(stderr,"DBG> Fatal Error: in SoSceneViewer::attachManip\n");
- fprintf(stderr," > manip->attach() failed!\n" );
- #endif
- }
-
- //
- // Add the manipulator below the selection node.
- // We keep manipulators off to the side so that they will
- // be ignored during highlighting. Since each manipulator
- // has a reset transform and a sensor on its target, this
- // is not a problem.
- //
- selection->addChild( theManip );
-
- // Add manip and path to the maniplist (maniplist will ref/unref)
- maniplist->append(selectedObject, theManip);
-
- theManip->unref();
-
- // Special case! If the manip is a jack manip, then replace
- // the dragPointDragger part with a path to the object itself!
- if ( manipMode == SV_JACK )
- theManip->replacePart("dragPointDragger", selectedObject );
- }
-
- xfPath->unref();
- }
-
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // This routine detaches the manipulators from all selected objects.
- //
- // Use: private
- void
- SoSceneViewer::detachManipFromAll()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- //
- // Loop from the end of the list to the start.
- //
- for (int i = selection->getNumSelected() - 1; i >= 0 ; i-- ) {
- SoPath *p = (SoPath *) (*selection)[i];
- detachManip( p );
- }
- }
-
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // This routine detaches a manipulator.
- //
- // Use: private
-
- void
- SoSceneViewer::detachManip(
- SoPath *p ) // Selection object that is being removed
- //
- ////////////////////////////////////////////////////////////////////////
- {
- //
- // Detach manip and remove from scene graph.
- //
- int which = maniplist->find(p);
- // See if this path is registered in the manip list.
- if (which != -1) {
- // remove from scene graph
- SoManipulator *manip = maniplist->getManip(which);
- manip->detach();
- selection->removeChild(manip);
-
- // remove from maniplist
- maniplist->remove(which);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // See the selection from the camera
- //
- // Use: public
- void
- SoSceneViewer::viewSelection()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- if (selection->getNumSelected() == 0) {
- viewAll();
- return;
- }
-
- SoPath *path = (*selection)[0];
- if(path != NULL) {
- getCamera()->viewAll(path);
- }
- else {
- viewAll();
- return;
- }
- }
-
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Create a color editor for the currently selected object.
- // Attachment code copied from SoXformManip.c++
- //
- // Use: private
- void
- SoSceneViewer::createColorEditor()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- if (colorEditor == NULL) {
- colorEditor = new SoXtColorEditor;
- colorEditor->setWYSIWYG(TRUE); //??? do this in app-defaults?
- colorEditor->setTitle("Diffuse Color");
- }
-
- SoMaterial *editMaterial = findMaterialForAttach( NULL );
-
- colorEditor->attach(&(editMaterial->diffuseColor), 0, editMaterial);
-
- colorEditor->show();
- }
-
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Find the appropriate material node in the scene graph to attach a material
- // editor to.
- //
- // Two possible cases:
- // [1] The path-tail is NOT a group. We search the siblings of the path
- // tail (including the tail itself) from right to left for a node
- // that is affected by materials (shapes or groups).
- // We stop the search if we come to a material node to the left of the
- // pathTail. If we find a node that IS affected by material, we will
- // insert a material node just before the path-tail. This is
- // because the editor should not affect nodes that appear
- // before attachPath in the scene graph.
- // [2] The path-tail IS a group. We search the children from left to
- // right for material nodes.
- // We stop the search if we come to a material node.
- // If we find a node that is affected by materials, we will insert a
- // material just before this node. This is because the editor for a
- // group should affect ALL nodes within that group.
- //
- // NOTE: For the purposes of this routine, we consider SoSwitch as different
- // from other types of group. This is because we don't want to put
- // the new node underneath the switch, but next to it.
- //
- // Use: private
- //
- SoMaterial *
- SoSceneViewer::findMaterialForAttach(
- const SoPath *target ) // path to start search from
- //
- ////////////////////////////////////////////////////////////////////////
- {
- int pathLength;
- SoPath *selectionPath;
- SoMaterial *editMtl;
-
- SbBool madeNewMtl = FALSE; // did we create a new material
- // node within this method?
-
-
- if ( ( selectionPath = (SoPath *) target ) == NULL ) {
- //
- // If no selection path is specified, then use the LAST path in the
- // current selection list.
- //
- selectionPath = (*selection)[selection->getNumSelected() - 1]; // last guy
- }
- pathLength = selectionPath->getLength();
-
- if ( pathLength <= 0 ) {
- fprintf( stderr, "No objects currently selected...\n" );
- return NULL;
- }
-
- #ifdef DEBUG
- if ( pathLength < 2 ) {
- fprintf( stderr, "Picked object has no parent...\n" );
- return NULL;
- }
- #endif
-
-
- // find 'group' and try to find 'editMtl'
- SoGroup *group;
- SoNode *node;
- int index, i;
-
- editMtl = NULL;
-
- if ( selectionPath->getTail()->isOfType( SoBaseKit::getClassTypeId() )) {
- // Nodekits have their own built in policy for creating new material
- // nodes. Allow them to contruct and return it.
- SoBaseKit *kit = (SoBaseKit *) selectionPath->getTail();
- // CHECKPART returns NULL if the part doesn't exist yet...
- editMtl = CHECKPART( kit, "material", SoMaterial );
- if ( editMtl == NULL ) {
- editMtl = GETPART( kit, "material", SoMaterial );
- madeNewMtl = TRUE;
- }
- }
-
- SbBool isTailGroup =
- selectionPath->getTail()->isOfType( SoGroup::getClassTypeId()) &&
- (!selectionPath->getTail()->isOfType( SoSwitch::getClassTypeId()));
-
- if ((editMtl == NULL) && ( !isTailGroup )) {
- //
- // CASE 1: The path-tail is not a group.
- // 'group' becomes the second to last node in the path.
- // We search the path tail and its siblings from right to left for a
- // mtl node.
- // We stop the search if we come to a shape node or a group node
- // to the left of the pathTail. If we find a shape or group, we
- // will insert a mtl just before the path-tail. This is
- // because the manipulator should not affect objects that appear
- // before selectionPath in the scene graph.
- //
- group = (SoGroup *) selectionPath->getNode(pathLength - 2);
- index = group->findChild( selectionPath->getTail() );
-
- for (i = index; (i >= 0) && (editMtl == NULL); i--){
- node = group->getChild(i);
- if (node->isOfType(SoMaterial::getClassTypeId())) // found SoMaterial
- editMtl = (SoMaterial *) node;
- else if ( i != index ) {
- if ( isAffectedByMaterial( node ) )
- break;
- }
- }
-
- if ( editMtl == NULL ) {
- editMtl = new SoMaterial;
- group->insertChild( editMtl, index );
- madeNewMtl = TRUE;
- }
- }
- else if (editMtl == NULL) {
- // CASE 2: The path-tail is a group.
- // 'group' becomes the path tail
- // We search the children from left to right for mtl nodes.
- // We stop the search if we come to a shape node or a group node.
- // If we find a shape or group, we will insert a mtl just
- // before this shape or group. This is because the editor
- // for a group should affect ALL objects within that group.
- //
- group = (SoGroup *) selectionPath->getTail();
- for (i = 0; (i < group->getNumChildren()) && (editMtl == NULL); i++ ) {
- node = group->getChild(i);
- if (node->isOfType(SoMaterial::getClassTypeId()))
- editMtl = (SoMaterial *) node;
- else if ( isAffectedByMaterial( node ) )
- break;
- }
-
- if ( editMtl == NULL ) {
- editMtl = new SoMaterial;
- group->insertChild( editMtl, i );
- madeNewMtl = TRUE;
- }
- }
-
- // If we just created the material node here, then set the ignore
- // flags for all fields in the node. This will cause the fields
- // to be inherited from their ancestors. The material editor will
- // undo these flags whenever it changes the value of a field
- if ( madeNewMtl == TRUE ) {
- editMtl->ambientColor.setIgnored( TRUE );
- editMtl->diffuseColor.setIgnored( TRUE );
- editMtl->specularColor.setIgnored( TRUE );
- editMtl->emissiveColor.setIgnored( TRUE );
- editMtl->shininess.setIgnored( TRUE );
- editMtl->transparency.setIgnored( TRUE );
- }
-
- // If any of the fields is ignored, then fill the value with the value
- // inherited from the rest of the scene graph
- if ( editMtl->ambientColor.isIgnored()
- || editMtl->diffuseColor.isIgnored()
- || editMtl->specularColor.isIgnored()
- || editMtl->emissiveColor.isIgnored()
- || editMtl->shininess.isIgnored()
- || editMtl->transparency.isIgnored() ){
-
- // Create a path to the material
- SoPath *mtlPath;
- if ( selectionPath->getTail()->isOfType( SoBaseKit::getClassTypeId() )) {
- SoBaseKit *kit = (SoBaseKit *) selectionPath->getTail();
- mtlPath = kit->createPathToPart( "material",
- SoMaterial::getClassTypeId(),
- TRUE, selectionPath );
- mtlPath->ref();
- }
- else {
- if ( !isTailGroup ) {
- // CASE 1: path-tail was NOT 'group' -- copy all but last entry
- mtlPath = new SoPath;
- mtlPath->copy(selectionPath, 0, pathLength - 1);
- }
- else {
- // CASE 2: path-tail was 'group' -- copy all of editPath
- mtlPath = new SoPath;
- mtlPath->copy(selectionPath, 0, pathLength);
- }
- mtlPath->ref();
- // add the material to the end of the path
- int mtlIndex = group->findChild(editMtl);
- mtlPath->append( mtlIndex );
- }
-
- // Pass the material node to an accumulate state callback
- // that will load any 'ignored' values with their inherited values.
- SoCallbackAction cba;
- cba.addPreTailCallback( SoSceneViewer::findMtlPreTailCB, editMtl);
- cba.apply( mtlPath );
-
- mtlPath->unref();
- }
-
-
- return( editMtl );
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Callback used by 'findMaterialForAttach' as part of the accumulate state
- // action. Returns 'PRUNE', which tells the action not to draw the
- // shape as part of the accum state action.
- // editor to.
- //
- // Use: private
- //
- SoCallbackAction::Response
- SoSceneViewer::findMtlPreTailCB( void *data, SoCallbackAction *accum,
- const SoNode * )
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoMaterial *mtl = (SoMaterial *) data;
-
- SbColor ambient, diffuse, specular, emissive;
- float shininess, transparency;
-
- accum->getMaterial( ambient, diffuse, specular, emissive,
- shininess, transparency );
-
- // inherit the accumulated values only in those fields being ignored.
- if ( mtl->ambientColor.isIgnored() )
- mtl->ambientColor.setValue( ambient );
- if ( mtl->diffuseColor.isIgnored() )
- mtl->diffuseColor.setValue( diffuse );
- if ( mtl->specularColor.isIgnored() )
- mtl->specularColor.setValue( specular );
- if ( mtl->emissiveColor.isIgnored() )
- mtl->emissiveColor.setValue( emissive );
- if ( mtl->shininess.isIgnored() )
- mtl->shininess.setValue( shininess );
- if ( mtl->transparency.isIgnored() )
- mtl->transparency.setValue( transparency );
-
- return SoCallbackAction::ABORT;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Find the appropriate transform node in the scene graph for attaching a
- // transform editor or manipulator.
- //
- // How we treat the 'center' field of the transform node:
- // If we need to create a new transform node:
- // set the 'center' to be the geometric center of all objects
- // affected by that transform.
- // If we find a transform node that already exists:
- // 'center' will not be changed.
- //
- // Three possible cases:
- // [1] The path-tail is a node kit. Just ask the node kit for a path
- // to the part called "transform"
- // [2] The path-tail is NOT a group. We search the siblings of the path
- // tail (including the tail itself) from right to left for a node
- // that is affected by transforms (shapes, groups, lights,cameras).
- // We stop the search if we come to a transform node to the left of
- // the pathTail. If we find a node that IS affected by transform,
- // we will insert a transform node just before the path-tail. This is
- // because the editor should not affect nodes that appear
- // before attachPath in the scene graph.
- // [3] The path-tail IS a group. We search the children from left to
- // right for transform nodes.
- // We stop the search if we come to a transform node.
- // If we find a node that is affected by transform, we will insert a
- // transform just before this node. This is because the editor for a
- // group should affect ALL nodes within that group.
- //
- // NOTE: For the purposes of this routine, we consider SoSwitch as different
- // from other types of group. This is because we don't want to put
- // the new node underneath the switch, but next to it.
- //
- // Use: private
- //
- SoPath *
- SoSceneViewer::findTransformForAttach(
- const SoPath *target ) // path to start search from
- //
- ////////////////////////////////////////////////////////////////////////
- {
- int pathLength;
- SoPath *selectionPath;
- SoTransform *editXform;
-
-
- if ( ( selectionPath = (SoPath *) target ) == NULL ) {
- //
- // If no selection path is specified, then use the LAST path in the
- // current selection list.
- //
- selectionPath = (*selection)[selection->getNumSelected() - 1];
- }
- pathLength = selectionPath->getLength();
-
- if ( pathLength <= 0 ) {
- fprintf( stderr, "No objects currently selected...\n" );
- return NULL;
- }
-
- #ifdef DEBUG
- if ( pathLength < 2 ) {
- fprintf( stderr, "Picked object has no parent...\n" );
- return NULL;
- }
- #endif
-
- // find 'group' and try to find 'editXform'
- SoGroup *group;
- SoNode *node;
- int index, i;
- SbBool isTailGroup, isTailKit;
- SbBool existedBefore = FALSE;
- SoPath *pathToXform = NULL;
-
- editXform = NULL;
-
- isTailGroup =
- ( selectionPath->getTail()->isOfType(SoGroup::getClassTypeId() )
- && !selectionPath->getTail()->isOfType(SoSwitch::getClassTypeId()));
-
- isTailKit = selectionPath->getTail()->isOfType(SoBaseKit::getClassTypeId());
-
- // CASE 1: The path-tail is a node kit.
- if ( isTailKit ) {
-
- // Nodekits have their own built in policy for creating new transform
- // nodes. Allow them to contruct and return a path to it.
- SoBaseKit *kit = (SoBaseKit *) selectionPath->getTail();
-
- // Before creating path, see if the transform part exists yet:
- if (CHECKPART(kit, "transform", SoTransform) != NULL)
- existedBefore = TRUE;
- else
- existedBefore = FALSE;
-
- pathToXform = kit->createPathToPart( "transform",
- SoTransform::getClassTypeId(),
- TRUE, selectionPath );
- pathToXform->ref();
-
- editXform = (SoTransform *) pathToXform->getTail();
- }
-
- if ( !isTailGroup && !isTailKit ) {
- //
- // CASE 2: The path-tail is not a group.
- // 'group' becomes the second to last node in the path.
- // We search the path tail and its siblings from right to left for a
- // transform node.
- // We stop the search if we come to a 'movable' node
- // to the left of the pathTail. If we find a movable node, we
- // will insert a transform just before the path-tail. This is
- // because the manipulator should not affect objects that appear
- // before selectionPath in the scene graph.
- //
- group = (SoGroup *) selectionPath->getNode(pathLength - 2);
- index = group->findChild( selectionPath->getTail() );
-
- for (i = index; (i >= 0) && (editXform == NULL); i--){
- node = group->getChild(i);
- if (node->isOfType(SoTransform::getClassTypeId())) // found an SoMaterial
- editXform = (SoTransform *) node;
- else if ( i != index ) {
- if ( !node->isOfType( SoManipulator::getClassTypeId() ) ) {
- if ( isAffectedByTransform( node ) )
- break;
- }
- }
- }
-
- if ( editXform == NULL ) {
- existedBefore = FALSE;
- editXform = new SoTransform;
- group->insertChild( editXform, index );
- }
- else
- existedBefore = TRUE;
- }
- else if ( !isTailKit ) {
- // CASE 3: The path-tail is a group.
- // 'group' becomes the path tail
- // We search the children from left to right for transform nodes.
- // We stop the search if we come to a movable node.
- // If we find a movable node, we will insert a transform just
- // before this node. This is because the editor
- // for a group should affect ALL objects within that group.
- //
- group = (SoGroup *) selectionPath->getTail();
- for (i = 0; (i < group->getNumChildren()) && (editXform == NULL); i++ ) {
- node = group->getChild(i);
- if (node->isOfType(SoTransform::getClassTypeId()))
- editXform = (SoTransform *) node;
- else if ( isAffectedByTransform( node ) )
- break;
- }
-
- if ( editXform == NULL ) {
- existedBefore = FALSE;
- editXform = new SoTransform;
- group->insertChild( editXform, i );
- }
- else
- existedBefore = TRUE;
- }
-
- // If we don't have a path yet (i.e., we weren't handed a nodekit path)
- // create the 'pathToXform'
- // by copying editPath and making the last node in the path be editXform
- if ( pathToXform == NULL ) {
- pathToXform = new SoPath;
- pathToXform->ref();
- if ( !isTailGroup )
- // CASE 2: path-tail was NOT 'group' -- copy all but last entry
- pathToXform->copy(selectionPath, 0, pathLength - 1);
- else
- // CASE 3: path-tail was 'group' -- copy all of editPath
- pathToXform->copy(selectionPath, 0, pathLength);
- // add the transform to the end
- int xfIndex = group->findChild(editXform);
- pathToXform->append( xfIndex );
- }
-
-
- // Now. If we created the transform node right here, right now, then
- // we will set the 'center' field based on the geometric center. We
- // don't do this if we didn't create the transform, because "maybe it
- // was that way for a reason."
- if ( existedBefore == FALSE ) {
- // First, find 'applyPath' by popping nodes off the path until you
- // reach a separator. This path will contain all nodes affected by
- // the transform at the end of 'pathToXform'
- SoPath *applyPath = new SoPath;
- applyPath->ref();
- applyPath->copy(pathToXform);
- for (int i = (applyPath->getLength() - 1); i >0; i-- ) {
- if (applyPath->getNode(i)->isOfType( SoSeparator::getClassTypeId()))
- break;
- applyPath->pop();
- }
-
- // Next, apply a bounding box action to applyPath, and reset the
- // bounding box just before the tail of 'pathToXform' (which is just
- // the editXform). This will assure that the only things included in
- // the resulting bbox will be those affected by the editXform.
- SoGetBoundingBoxAction bboxAction;
- bboxAction.setResetPath(pathToXform,TRUE,SoGetBoundingBoxAction::BBOX );
- bboxAction.apply(applyPath);
-
- // Get the center of the bbox in world space...
- SbVec3f worldBoxCenter = bboxAction.getBoundingBox().getCenter();
-
- // Convert it into local space of the transform...
- SbVec3f localBoxCenter;
- SoGetMatrixAction ma;
- ma.apply( pathToXform );
- ma.getInverse().multVecMatrix( worldBoxCenter, localBoxCenter );
-
- // Finally, set the center value...
- editXform->center.setValue( localBoxCenter );
- }
-
- return( pathToXform );
- }
-
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Create a material editor for the currently selected object.
- //
- // Use: private
- void
- SoSceneViewer::createMaterialEditor()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- if (materialEditor == NULL)
- materialEditor = new SoXtMaterialEditor;
- materialEditor->show();
-
- materialEditor->attach( findMaterialForAttach( NULL ) );
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Create a transform editor for the currently selected object
- //
- // Use: private
- void
- SoSceneViewer::createTransformSliderSet()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoPath *editTransformPath;
- SoTransform *editTransform;
-
- // get path to a transform to edit
- if ( ( editTransformPath = findTransformForAttach( NULL )) == NULL )
- return;
-
- // the tail of the path is a transform for us!
- editTransformPath->ref();
- editTransform = (SoTransform *) editTransformPath->getTail();
- editTransformPath->unref();
-
- // Nuke the old slider set and get a new one
- if (transformSliderSet == NULL)
- transformSliderSet = new SoXtTransformSliderSet();
- transformSliderSet->build();
- transformSliderSet->setNode(editTransform);
- transformSliderSet->show();
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Set fog on/off.
- //
- // Use: private
- void
- SoSceneViewer::setFog(SbBool flag)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- fogFlag = flag;
-
- if (fogFlag)
- environment->fogType.setValue( SoEnvironment::EXPONENTIAL );
- else
- environment->fogType.setValue( SoEnvironment::NONE );
-
- // ??? set the density here instead of the constructor because the
- // ??? farDistance doesn't have meaningful values untill the viewers
- // ??? change it (autoClipping).
- environment->fogDensity.setValue( 1.0
- / (FOG_FUDGE * getCamera()->farDistance.getValue()) );
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Set AA-ing on/off.
- //
- // Use: private
- void
- SoSceneViewer::setAntialiasing(SbBool flag)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- antialiasingFlag = flag;
-
- if (antialiasingFlag)
- currentViewer->setAntialiasing( TRUE, 3 );
- else
- currentViewer->setAntialiasing( FALSE, 1 );
-
- sceneGraph->notify( NULL ); // forces a redraw
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Invokes color editor on ambient lighting color.
- void
- SoSceneViewer::editAmbientColor()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- if ( ambientColorEditor == NULL ) {
- ambientColorEditor = new SoXtColorEditor;
- ambientColorEditor->setTitle( "Ambient Lighting" );
- ambientColorEditor->addColorChangedCallback(
- SoSceneViewer::ambientColorCallback, this );
- }
-
- // Normalize ambient intensity
- SbColor ambCol;
- ambCol = environment->ambientColor.getValue();
- ambCol *= environment->ambientIntensity.getValue();
- environment->ambientIntensity.setValue( 1.0 );
- environment->ambientColor.setValue( ambCol );
-
- ignoreCallback = TRUE;
- ambientColorEditor->setColor( environment->ambientColor.getValue() );
- ignoreCallback = FALSE;
- ambientColorEditor->show();
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Callback proc invoked by the color editor, this changes the scene's
- // ambient lighting color.
- //
- // Use: static, private
- //
- void
- SoSceneViewer::ambientColorCallback(void *userData, const SbColor *color)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoSceneViewer *sv = (SoSceneViewer *) userData;
-
- if (sv->ignoreCallback)
- return;
-
- sv->environment->ambientColor.setValue( *color );
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Invokes color editor on background color.
- void
- SoSceneViewer::editBackgroundColor()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- if ( backgroundColorEditor == NULL ) {
- backgroundColorEditor = new SoXtColorEditor;
- backgroundColorEditor->setTitle( "Background Color" );
- backgroundColorEditor->addColorChangedCallback(
- SoSceneViewer::backgroundColorCallback, this );
- }
- ignoreCallback = TRUE;
- backgroundColorEditor->setColor(getBackgroundColor());
- ignoreCallback = FALSE;
- backgroundColorEditor->show();
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Callback proc invoked by the color editor, this changes the current
- // viewer's background color.
- //
- // Use: static, private
- //
- void
- SoSceneViewer::backgroundColorCallback(void *userData, const SbColor *c)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoSceneViewer *sv = (SoSceneViewer *) userData;
-
- if (sv->ignoreCallback)
- return;
-
- sv->currentViewer->setBackgroundColor( *c );
-
- // keep fog color up to date with bkg color
- sv->environment->fogColor.setValue( *c );
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // This will remove any cameras under root.
- //
- // Use: private
- void
- SoSceneViewer::removeCameras(SoGroup *root)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoSearchAction sa;
- sa.setType(SoCamera::getClassTypeId());
- sa.setFindAll(TRUE);
- sa.apply(root);
-
- // remove those cameras!
- SoPathList paths = sa.getPaths();
- for (int i = 0; i < paths.length(); i++) {
- SoPath *p = paths[i];
- SoCamera *cam = (SoCamera *) p->getNodeFromTail(0);
- SoGroup *group = (SoGroup *) p->getNodeFromTail(1);
- group->removeChild(cam);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Reads the given file and insert the geometry under the selection
- // node. If the node didn't have any children, the viewAll() method is
- // automatically called.
- //
- // Use: private
- SbBool
- SoSceneViewer::readFile(const char *filename)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoInput in;
- if (! in.openFile(filename)) {
-
- // display an error dialog
- char str[100];
- strcpy(str, "Error opening file: ");
- strcat(str, filename);
- SoXt::createSimpleErrorDialog(mgrWidget, "File Error Dialog", str);
- return FALSE;
- }
-
- SbBool hadNoChildren = (selection->getNumChildren() == 0);
-
- // add nodes under selection, not sceneGraph
- SoNode *node;
- SbBool ok;
- while ((ok = SoDB::read(&in, node)) && (node != NULL))
- selection->addChild(node);
-
- // display error dialog if there were reading errors
- if (!ok) {
- char str[100];
- strcpy(str, "Error reading file: ");
- strcat(str, filename);
- SoXt::createSimpleErrorDialog(mgrWidget, "File Error Dialog", str);
- return FALSE;
- }
-
- // remove any cameras under selection which were just added
- removeCameras(selection);
-
- if (hadNoChildren) {
- viewAll();
- saveHomePosition();
- }
-
- return TRUE;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Read environment data. We expect the following nodes:
- //
- // Group {
- // Label { "SoSceneViewer Environment v3.0" }
- // Camera {}
- // Environment {}
- // LightGroup {
- // Switch { DirectionalLight } # 1
- // ...
- // Switch { DirectionalLight } # 6
- // }
- // DirectionalLight {} # optional headlight
- // }
- //
- // Use: private
- SbBool
- SoSceneViewer::readEnvFile(const char *filename)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoInput in;
- SoNode *n;
- SoGroup *g = NULL;
- SoLabel *l = NULL;
- SbBool isValid = FALSE;
- SbBool ok=FALSE;
- while(!ok)
- {
- if (! in.openFile(filename)) {
- // display an error dialog
- char str[100];
- strcpy(str, "Error opening file: ");
- strcat(str, filename);
- SoXt::createSimpleErrorDialog(mgrWidget, "File Error Dialog", str);
- return FALSE;
- }
-
-
- if ((ok = SoDB::read(&in, n)) && n != NULL) {
- // we expect a label first
- n->ref();
- if (n->isOfType(SoLabel::getClassTypeId())) {
- l = (SoLabel *) n;
- isValid = (strcmp(l->label.getValue().getString(),
- SV_ENV_LABEL) == 0);
- }
- n->unref();
- }
- }
- // else if (!ok) {
- //display error dialog if there were reading errors
- // char str[100];
- // strcpy(str, "Error reading file: ");
- // strcat(str, filename);
- // SoXt::createSimpleErrorDialog(mgrWidget, "File Error Dialog", str);
- // return FALSE;
- // }
-
- // if ok, read the rest.
- if (isValid) {
- // Camera
- if (SoDB::read(&in, n) != FALSE && (n != NULL)) {
- n->ref();
- if (n->isOfType(SoPerspectiveCamera::getClassTypeId())) {
- // viewers need to be detached from the old camera
- // and attached to the new. both cameras must be in
- // the scene graph for this to happen smoothly.
- SoPerspectiveCamera *newCamera = (SoPerspectiveCamera *) n;
- lightsCameraEnvironment->insertChild(newCamera, 0);
- setCamera(newCamera);
- lightsCameraEnvironment->removeChild(camera);
- camera = newCamera;
- }
- n->unref();
- }
- // Environment
- if (SoDB::read(&in, n) != FALSE && (n != NULL)) {
- n->ref();
- if (n->isOfType(SoEnvironment::getClassTypeId())) {
- lightsCameraEnvironment->replaceChild(environment, n);
- environment = (SoEnvironment *) n;
- }
- n->unref();
- }
- // Light group
- if (SoDB::read(&in, n) != FALSE && (n != NULL)) {
- n->ref();
- if (n->isOfType(SoGroup::getClassTypeId())) {
-
- // remove all of the existing lights
- for (int i = lightDataList.length(); i > 0; i--)
- removeLight( (SvLightData *) lightDataList[i-1] );
-
- lightsCameraEnvironment->replaceChild(lightGroup, n);
- lightGroup = (SoGroup *) n;
-
- // now create a light entry for each new light
- for (i=0; i < lightGroup->getNumChildren(); i++) {
- SoNode *node = lightGroup->getChild(i);
- if (node->isOfType(SoSwitch::getClassTypeId())) {
- SoSwitch *sw = (SoSwitch *) node;
- node = sw->getChild(0);
- if (node->isOfType(SoLight::getClassTypeId()))
- addLightEntry((SoLight *)node, sw);
- }
- }
- }
- n->unref();
- }
- // Headlight (optional) - if not there, turn headlight off
- if (SoDB::read(&in, n) != FALSE && (n != NULL)) {
- n->ref();
- if (n->isOfType(SoDirectionalLight::getClassTypeId())) {
- SoDirectionalLight *headlight = getHeadlight();
- SoDirectionalLight *newLight = (SoDirectionalLight *) n;
- headlight->intensity.setValue(newLight->intensity.getValue());
- headlight->color.setValue(newLight->color.getValue());
- headlight->direction.setValue(newLight->direction.getValue());
- setHeadlight(TRUE);
- }
- n->unref();
- }
- else setHeadlight(FALSE);
- }
- else {
- fprintf(stderr, "Sorry, file is not formatted correctly\n");
- }
-
- return TRUE;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // This routine is called to get a file name. Either a motif
- // dialog or the showcase gizmo are used.
- //
- // Use: private
- void
- SoSceneViewer::getFileName()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- if ( useShowcaseBrowser ) {
- // use the showcase browser
- if (browser == NULL) {
- browser = new SoXtFileBrowser;
- browser->setCallback(SoSceneViewer::browserCB, this);
- }
-
- if (browser->isVisible())
- browser->hide();
-
- browser->show();
- }
- else {
- // use a motif file selection dialog
- if (fileDialog == NULL) {
- Arg args[5];
- int n = 0;
-
- // unmanage when ok/cancel are pressed
- XtSetArg(args[n], XmNautoUnmanage, TRUE); n++;
- fileDialog = XmCreateFileSelectionDialog(
- XtParent(mgrWidget), "File Dialog", args, n);
-
- XtAddCallback(fileDialog, XmNokCallback,
- (XtCallbackProc)SoSceneViewer::fileDialogCB,
- (XtPointer)this);
- }
-
- // manage the dialog
- XtManageChild(fileDialog);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Showcase browser gizmo callback.
- //
- void
- SoSceneViewer::browserCB(void *sv, const char *filename)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- ((SoSceneViewer *)sv)->doFileIO(filename);
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Motif file dialog callback.
- //
- void
- SoSceneViewer::fileDialogCB(Widget, SoSceneViewer *sv,
- XmFileSelectionBoxCallbackStruct *data)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- // Get the file name
- char *filename;
- XmStringGetLtoR(data->value,
- (XmStringCharSet) XmSTRING_DEFAULT_CHARSET, &filename);
-
- // Use that file
- sv->doFileIO(filename);
-
- XtFree(filename);
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // detach everything and nuke the existing scene.
- //
- // Use: private
- void
- SoSceneViewer::deleteScene()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- // deselect everything (also detach manips)
- selection->deselectAll();
-
- // temporaly remove the light manips
- removeAttachedLightManipGeometry();
-
- // remove the geometry under the selection node
- for (int i = selection->getNumChildren(); i>0; i--)
- selection->removeChild(i-1);
-
- // add the light manips back in
- addAttachedLightManipGeometry();
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Read/Write to the given file name, given the current file mode.
- //
- // Use: private
- void
- SoSceneViewer::doFileIO(const char *file)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SbBool okFile;
-
- switch (fileMode) {
- case SV_FILE_OPEN:
- deleteScene();
- okFile = readFile(file);
- break;
- case SV_FILE_IMPORT:
- okFile = readFile(file);
- break;
- case SV_FILE_SAVE_AS:
- okFile = writeFile(file);
- break;
- case SV_FILE_READ_ENV:
- readEnvFile(file);
- break;
- case SV_FILE_SAVE_ENV:
- writeEnvFile(file);
- break;
- default:
- fprintf(stderr, "Wrong file mode %d passed!\n", fileMode);
- return;
- }
-
- // save the new file name so we can simply use "Save" instead of
- // "Save As" next time around.
- if (fileMode == SV_FILE_OPEN || fileMode == SV_FILE_SAVE_AS) {
-
- // save the current file name
- delete fileName;
- if (okFile && file != NULL)
- fileName = strdup(file);
- else
- fileName = NULL;
- }
-
- // enable/disable cmd key shortcuts and menu items
- updateCommandAvailability();
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Saves the scene to the current file.
- //
- // Use: private
- void
- SoSceneViewer::save()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- if (fileName != NULL) {
- SbBool ok = writeFile(fileName);
- if (!ok) {
- delete fileName;
- fileName = NULL;
- }
- }
- else {
- fileMode = SV_FILE_SAVE_AS;
- getFileName();
- }
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Removes the attached light manips geometry from the scene. This
- // is used for file writting,...
- //
- // Use: private
- void
- SoSceneViewer::removeAttachedLightManipGeometry()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoManipulator *manip;
- int index;
-
- for (int i = 0; i < lightDataList.length(); i++ ) {
- manip = ((SvLightData *) lightDataList[i])->manip;
-
- // check to make sure the manip has been added to the scene
- if ( manip != NULL && (index = selection->findChild(manip)) >= 0)
- selection->removeChild( index );
- }
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Add the attached light manips geometry back into the scene. This
- // is called after the geometry has been temporaly revomed (used for file
- // writting).
- //
- // Use: private
- void
- SoSceneViewer::addAttachedLightManipGeometry()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoManipulator *manip;
-
- for (int i = 0; i < lightDataList.length(); i++ ) {
- manip = ((SvLightData *) lightDataList[i])->manip;
-
- // check to make sure the manip was previously in the
- // scene (i.e. attached to a light).
- if ( manip != NULL && manip->isAttached() &&
- selection->findChild(manip) < 0)
- selection->addChild( manip );
- }
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Write the nodes under the selection node to the given file name.
- //
- // Use: private
- SbBool
- SoSceneViewer::writeFile(const char *filename)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoWriteAction wa;
- SoManipulator *manip;
-
- if (! wa.getOutput()->openFile(filename)) {
-
- // display an error dialog
- char str[100];
- strcpy(str, "Error creating file: ");
- strcat(str, filename);
- SoXt::createSimpleErrorDialog(mgrWidget, "File Error Dialog", str);
-
- return FALSE;
- }
-
- // temporarily remove all manips from the scene graph.
- // You can leave them attached, just make sure they don't write out.
- for (int m = 0; m < maniplist->getLength(); m++ ) {
- manip = maniplist->getManip(m);
- selection->removeChild(manip);
- }
-
- // Do the same for all the light manips
- removeAttachedLightManipGeometry();
-
- // write out all the children of the selection node
- for (int i = 0; i < selection->getNumChildren(); i++)
- wa.apply(selection->getChild(i));
- wa.getOutput()->closeFile();
-
- // Now put the manips back in the scene graph.
- for ( m = 0; m < maniplist->getLength(); m++ ) {
- manip = maniplist->getManip(m);
- selection->addChild(manip);
- }
-
- // put the light manips back in the scene graph.
- addAttachedLightManipGeometry();
-
- return TRUE;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Write the Enviroment nodes (camera and lights) to the given
- // file name.
- //
- // Use: private
- SbBool
- SoSceneViewer::writeEnvFile(const char *filename)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoWriteAction wa;
-
- if (! wa.getOutput()->openFile(filename)) {
-
- // display an error dialog
- char str[100];
- strcpy(str, "Error creating file: ");
- strcat(str, filename);
- SoXt::createSimpleErrorDialog(mgrWidget, "File Error Dialog", str);
-
- return FALSE;
- }
-
- // write out the environment including the headlight
- wa.apply(envLabel);
- wa.apply(camera);
- wa.apply(environment);
- wa.apply(lightGroup);
- if (isHeadlight())
- wa.apply(getHeadlight());
-
- wa.getOutput()->closeFile();
-
- return TRUE;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Print the scene using a custom print dialog.
- //
- // Use: private
- void
- SoSceneViewer::print()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- if (printDialog == NULL) {
- printDialog = new SoXtPrintDialog;
- printDialog->setTitle("SceneViewer Printing");
- printDialog->addBeforePrintCallback(
- SoSceneViewer::beforePrintCallback, (void *) this);
- printDialog->addAfterPrintCallback(
- SoSceneViewer::afterPrintCallback, (void *) this);
- }
-
- printDialog->show();
- //printScreen(mysv);
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Temporarily remove highlighting and manips from the scene. They
- // will all be restored after the printing is done.
- //
- // Use: private, static
- void
- SoSceneViewer::beforePrintCallback(void *uData, SoXtPrintDialog *)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoSceneViewer *sv = (SoSceneViewer *)uData;
-
- // temporarily remove all manips from the scene graph.
- // You can leave them attached, just make sure they don't write out.
- for (int m = 0; m < sv->maniplist->getLength(); m++ )
- sv->selection->removeChild( sv->maniplist->getManip(m) );
-
- // Do the same for all the light manips
- sv->removeAttachedLightManipGeometry();
-
- // remove the hilighting (saving the current highlight style)
- sv->savedHighlight = sv->selection->getHighlightStyle();
- sv->selection->setHighlightStyle(NULL);
-
- // if the current viewer is the examiner viewer, turn the
- // feedback axis off while we print
- if (sv->whichViewer == SV_VWR_EXAMINER) {
- SoXtExaminerViewer *exam = (SoXtExaminerViewer *) sv->currentViewer;
- sv->feedbackShown = exam->isFeedbackVisible();
- exam->setFeedbackVisibility(FALSE);
- }
-
- //
- // Send the render area size and scene graph to the print dialog
- //
- Widget widget = sv->getRenderAreaWidget();
- if (widget != NULL) {
- Arg args[2];
- int n = 0;
- short _w, _h; // HAS to be shorts
- XtSetArg(args[n], XtNheight, &_h); n++;
- XtSetArg(args[n], XtNwidth, &_w); n++;
- XtGetValues(widget, args, n);
- sv->printDialog->setPrintSize((int)_w, (int)_h);
- }
-
- // set the scene to print
- sv->printDialog->setSceneGraph(sv->sceneGraph);
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Called after printing is done. Add the manips back into the
- // scene and restore the highliting style.
- //
- // Use: private, static
- void
- SoSceneViewer::afterPrintCallback(void *uData, SoXtPrintDialog *)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoSceneViewer *sv = (SoSceneViewer *)uData;
-
- // put the manips back in the scene graph.
- for (int m = 0; m < sv->maniplist->getLength(); m++ )
- sv->selection->addChild( sv->maniplist->getManip(m) );
-
- // put the light manips back in the scene graph.
- sv->addAttachedLightManipGeometry();
-
- // restore the highting style
- sv->selection->setHighlightStyle( sv->savedHighlight );
-
- // restor the examiner feedback
- if (sv->whichViewer == SV_VWR_EXAMINER) {
- SoXtExaminerViewer *exam = (SoXtExaminerViewer *) sv->currentViewer;
- exam->setFeedbackVisibility( sv->feedbackShown );
- }
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Static routine for processing topbar menu events.
- // When the menu is created, it stores pointer to the SoSceneViewer
- // in the client_data, so that we can tell which SoSceneViewer needs
- // the event.
- //
- // Use: private, static
- //
- void
- SoSceneViewer::processTopbarEvent(
- Widget, // Which widget? I don't care
- SoSceneViewerData *data, // Pointer to button/SoSceneViewer
- XmAnyCallbackStruct *cb ) // X garbage
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoSceneViewer *sv = data->classPt;
- Time eventTime = cb->event->xbutton.time;
-
- switch (data->id) {
-
- //
- // File
- //
-
- case SV_FILE_ABOUT:
- sv->showAboutDialog();
- break;
-
- case SV_FILE_NEW:
- sv->deleteScene();
- delete sv->fileName;
- sv->fileName = NULL;
- break;
-
- case SV_FILE_OPEN:
- case SV_FILE_IMPORT:
- case SV_FILE_SAVE_AS:
- case SV_FILE_READ_ENV:
- case SV_FILE_SAVE_ENV:
- sv->fileMode = data->id;
- sv->getFileName();
- break;
-
- case SV_FILE_SAVE:
- sv->save();
- break;
-
- case SV_FILE_PRINT:
- sv->print();
- break;
- case SV_FILE_QUIT:
- delete sv;
- exit(0);
- break;
-
- //
- // Edit
- //
-
- case SV_EDIT_PICK_PARENT:
- sv->pickParent();
- break;
- case SV_EDIT_PICK_ALL:
- sv->pickAll();
- break;
- case SV_EDIT_CUT:
- sv->clipboard->copy((SoPathList *)sv->selection->getList(), eventTime);
- sv->selection->destroy();
- sv->updateCommandAvailability();
- break;
- case SV_EDIT_COPY:
- sv->clipboard->copy((SoPathList *)sv->selection->getList(), eventTime);
- break;
- case SV_EDIT_PASTE:
- sv->clipboard->paste(eventTime, pasteDoneCB, sv);
- break;
- case SV_EDIT_DELETE:
- sv->selection->destroy();
- sv->updateCommandAvailability();
- break;
-
- //
- // Viewing
- //
-
- case SV_VIEW_PICK:
- sv->setViewing(! sv->isViewing());
- if(! sv->isViewing())
- {
- #ifdef MYDEBUG
- printf("TIMER OFF, from pick menu\n");
- #endif
- timersensor->unschedule();
- timerflag=0;
- }
- else
- {
- #ifdef MYDEBUG
- printf("TIMER ON, from pick menu\n");
- #endif
- timersensor->schedule(SbTime((unsigned long)DATATIME));
- timerflag=1;
-
- }
- break;
- #ifdef EXPLORER
- case SV_VIEW_USER:
- sv->userModeFlag = !sv->userModeFlag;
- if (sv->userModeFlag)
- sv->currentViewer->setEventCallback(sv->userModeCB, sv->userModedata);
- else
- sv->currentViewer->setEventCallback(NULL, NULL);
- break;
- #endif
-
- case SV_VIEW_EXAMINER:
- sv->switchToViewer(SV_VWR_EXAMINER);
- break;
- case SV_VIEW_WALK:
- sv->switchToViewer(SV_VWR_WALK);
- break;
- case SV_VIEW_PLANE:
- sv->switchToViewer(SV_VWR_PLANE);
- break;
- case SV_VIEW_FLY:
- sv->switchToViewer(SV_VWR_FLY);
- break;
-
- case SV_VIEW_SELECTION:
- sv->viewSelection();
- break;
-
- case SV_VIEW_SCREEN_TRANSPARENCY:
- sv->setTransparencyType(SoGLRenderAction::SCREEN_DOOR);
- break;
- case SV_VIEW_BLEND_TRANSPARENCY:
- sv->setTransparencyType(SoGLRenderAction::BLEND);
- break;
- case SV_VIEW_DELAY_BLEND_TRANSPARENCY:
- sv->setTransparencyType(SoGLRenderAction::DELAYED_BLEND);
- break;
- case SV_VIEW_SORT_BLEND_TRANSPARENCY:
- sv->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_BLEND);
- break;
-
- case SV_VIEW_FOG:
- sv->setFog(! sv->fogFlag);
- break;
- case SV_VIEW_ANTIALIASING:
- sv->setAntialiasing(! sv->antialiasingFlag);
- break;
- case SV_VIEW_BKG_COLOR:
- sv->editBackgroundColor();
- break;
-
-
- //
- // Editors
- //
- case SV_EDITOR_MATERIAL:
- sv->createMaterialEditor();
- break;
-
- case SV_EDITOR_TRANSFORM:
- sv->createTransformSliderSet();
- break;
-
- case SV_EDITOR_COLOR:
- sv->createColorEditor();
- break;
-
- //
- // Selection
- //
- case SV_SEL_SINGLE_SELECT:
- sv->selection->setSelectionPolicy(SoSelection::SINGLE);
- break;
-
- case SV_SEL_TOGGLE_SELECT:
- sv->selection->setSelectionPolicy(SoSelection::TOGGLE);
- break;
-
- case SV_SEL_SHIFT_SELECT:
- sv->selection->setSelectionPolicy(SoSelection::SHIFT);
- break;
-
- case SV_SEL_LINE_HIGHLIGHT:
- sv->selection->setHighlightStyle(sv->lineHighlight);
- break;
- case SV_SEL_BBOX_HIGHLIGHT:
- sv->selection->setHighlightStyle(sv->boxHighlight);
- break;
- case SV_SEL_NO_HIGHLIGHT:
- sv->selection->setHighlightStyle(NULL);
- break;
-
- case SV_SEL_HIGHLIGHT_COLOR:
- sv->editHighlightColor();
- break;
-
- //
- // Manips
- //
- case SV_MANIP_TRACKBALL:
- sv->curManip = (sv->curManip == SV_TRACKBALL) ? SV_NONE : SV_TRACKBALL;
- if ( sv->curManipReplaces )
- sv->replaceAllManips( sv->curManip );
- break;
-
- case SV_MANIP_HANDLEBOX:
- sv->curManip = (sv->curManip == SV_HANDLEBOX) ? SV_NONE : SV_HANDLEBOX;
- if ( sv->curManipReplaces )
- sv->replaceAllManips( sv->curManip );
- break;
-
- case SV_MANIP_JACK:
- sv->curManip = (sv->curManip == SV_JACK) ? SV_NONE : SV_JACK;
- if ( sv->curManipReplaces )
- sv->replaceAllManips( sv->curManip );
- break;
-
- case SV_MANIP_XFBOX:
- sv->curManip = (sv->curManip == SV_XFBOX) ? SV_NONE : SV_XFBOX;
- if ( sv->curManipReplaces )
- sv->replaceAllManips( sv->curManip );
- break;
-
- case SV_MANIP_DRAGPOINT:
- sv->curManip = (sv->curManip == SV_DRAGPOINT) ? SV_NONE : SV_DRAGPOINT;
- if ( sv->curManipReplaces )
- sv->replaceAllManips( sv->curManip );
- break;
-
- case SV_MANIP_NONE:
- sv->curManip = SV_NONE;
- if ( sv->curManipReplaces )
- sv->detachManipFromAll();
- break;
- case SV_MANIP_REPLACE_ALL:
- // Toggle the value of 'curManipReplaces'
- sv->curManipReplaces = ( sv->curManipReplaces == TRUE) ? FALSE : TRUE;
-
- if ( sv->curManipReplaces )
- sv->replaceAllManips( sv->curManip );
- break;
-
- //
- // Lights
- //
- case SV_LIGHT_AMBIENT_EDIT: sv->editAmbientColor(); break;
- case SV_LIGHT_ADD_DIRECT: sv->addLight(new SoDirectionalLight); break;
- case SV_LIGHT_ADD_POINT: sv->addLight(new SoPointLight); break;
- case SV_LIGHT_ADD_SPOT: sv->addLight(new SoSpotLight); break;
-
- case SV_LIGHT_TURN_ON:
- case SV_LIGHT_TURN_OFF:
- {
- SbBool onFlag = (data->id == SV_LIGHT_TURN_ON);
- for (int i=0; i < sv->lightDataList.length(); i++)
- sv->turnLightOnOff((SvLightData *) sv->lightDataList[i], onFlag);
- sv->turnLightOnOff( sv->headlightData, onFlag);
- }
- break;
- case SV_LIGHT_SHOW_ALL:
- case SV_LIGHT_HIDE_ALL:
- {
- SbBool onFlag = (data->id == SV_LIGHT_SHOW_ALL);
- for (int i=0; i < sv->lightDataList.length(); i++)
- sv->editLight((SvLightData *) sv->lightDataList[i], onFlag);
- }
- break;
-
- } // endswitch( topbar button )
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Adds the given light to the scene and to the menu.
- //
- // Use: private
- //
- void
- SoSceneViewer::addLight(SoLight *light)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- // create the switch and light node and add it to the scene
- SoSwitch *lightSwitch = new SoSwitch;
- lightGroup->addChild(lightSwitch);
- lightSwitch->addChild(light);
- SWITCH_LIGHT_ON(lightSwitch);
-
- // add the light entry for the new light
- SvLightData *data = addLightEntry(light, lightSwitch);
-
- //
- // Try to come up with some meaningfull default position base
- // of the current camera view volume.
- //
- SbViewVolume vv;
- camera->getViewVolume(vv);
- SbVec3f forward = - vv.zVector();
- SbVec3f center = camera->position.getValue() + forward *
- (camera->nearDistance.getValue() + camera->farDistance.getValue()) / 2.0;
- SbVec3f position( vv.ulf + forward * vv.nearToFar * .25 );
-
- if (data->type == SoLight::DIRECTIONAL) {
- SoDirectionalLight *light = (SoDirectionalLight *) data->light;
- // the position of the light will be given to the manip
- // since the light doesn't have any position field
- // Don't change the direction for now. If we change the direction,
- // then the placement of the manipulator during editLight() will be
- // screwy. This is because the translation given there is relative
- // to the rotated space that the manipulator is in after it is
- // rotated to line up with the light's direction.
- // light->direction = center - position;
- }
- else if (data->type == SoLight::POINT) {
- SoPointLight *light = (SoPointLight *) data->light;
- light->location = position;
- // no direction for this light
- }
- else if (data->type == SoLight::SPOT) {
- SoSpotLight *light = (SoSpotLight *) data->light;
- light->location = position;
- light->direction = center - position;
- }
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Creates and append the light data struct, and adds a menu entry
- // for the light.
- //
- // Use: private
- //
- SvLightData *
- SoSceneViewer::addLightEntry(SoLight *light, SoSwitch *lightSwitch)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- //
- // create the light data
- //
-
- SvLightData *data = new SvLightData;
- lightDataList.append(data);
- data->light = light;
- data->lightSwitch = lightSwitch;
- data->classPt = this;
- data->colorEditor = NULL;
- data->manip = NULL;
- if (light->isOfType(SoDirectionalLight::getClassTypeId()))
- data->type = SoLight::DIRECTIONAL;
- else if (light->isOfType(SoPointLight::getClassTypeId()))
- data->type = SoLight::POINT;
- else if (light->isOfType(SoSpotLight::getClassTypeId()))
- data->type = SoLight::SPOT;
- else
- fprintf(stderr, "Wrong light type!!\n");
-
- // set the correct label name
- char *str;
- switch (data->type) {
- case SoLight::DIRECTIONAL: str = "Directional "; break;
- case SoLight::POINT: str = "Point "; break;
- case SoLight::SPOT: str = "Spot "; break;
- }
- data->name = strdup(str);
-
- //
- // by default attach the light manipulator to show the light
- //
- editLight(data, TRUE);
-
- //
- // add the menu entry
- //
- addLightMenuEntry(data);
-
- return data;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // build the light menu entry for the given light.
- //
- // Use: private
- //
- void
- SoSceneViewer::addLightMenuEntry(SvLightData *data)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- //
- // create the motif menu entry
- //
- Arg args[1];
-
- Widget menu = menuItems[SV_LIGHT].widget;
-
- // makes sure menu has been built
- if (menu == NULL)
- return;
-
- // create the submenu widget, adding a callback to update the toggles
- data->submenuWidget = XmCreatePulldownMenu(menu, NULL, NULL, 0);
- XtAddCallback(data->submenuWidget, XmNmapCallback,
- (XtCallbackProc) SoSceneViewer::lightSubmenuDisplay,
- (XtPointer) data);
-
- // create a cascade menu entry which will bring the submenu
- XtSetArg(args[0], XmNsubMenuId, data->submenuWidget);
- data->cascadeWidget = XtCreateWidget(data->name,
- xmCascadeButtonGadgetClass, menu, args, 1);
-
- // add "on/off" toggle
- data->onOffWidget = XtCreateWidget("On/Off", xmToggleButtonGadgetClass,
- data->submenuWidget, NULL, 0);
- XtAddCallback(data->onOffWidget, XmNvalueChangedCallback,
- (XtCallbackProc) SoSceneViewer::lightToggleCB, (XtPointer) data);
-
- // add "Icon" toggle
- data->iconWidget = XtCreateWidget("Icon", xmToggleButtonGadgetClass,
- data->submenuWidget, NULL, 0);
- XtAddCallback(data->iconWidget, XmNvalueChangedCallback,
- (XtCallbackProc) SoSceneViewer::editLightToggleCB, (XtPointer) data);
-
- // add "Edit Color" toggle
- data->editColorWidget = XtCreateWidget("Edit Color", xmPushButtonGadgetClass,
- data->submenuWidget, NULL, 0);
- XtAddCallback(data->editColorWidget, XmNactivateCallback,
- (XtCallbackProc) SoSceneViewer::editLightColorCB, (XtPointer) data);
-
- // add "Remove" entry
- data->removeWidget = XtCreateWidget("Remove", xmPushButtonGadgetClass,
- data->submenuWidget, NULL, 0);
- XtAddCallback(data->removeWidget, XmNactivateCallback,
- (XtCallbackProc) SoSceneViewer::removeLightCB, (XtPointer) data);
-
- // manage children
- XtManageChild(data->onOffWidget);
- XtManageChild(data->iconWidget);
- XtManageChild(data->editColorWidget);
- XtManageChild(data->removeWidget);
- XtManageChild(data->cascadeWidget);
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Called by "On/Off" light menu entry when toggle changes.
- //
- // Use: static private
- //
- void
- SoSceneViewer::lightToggleCB(Widget toggle, SvLightData *data, void *)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- data->classPt->turnLightOnOff(data, XmToggleButtonGetState(toggle));
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Turn the given light on or off.
- //
- // Use: private
- //
- void
- SoSceneViewer::turnLightOnOff(SvLightData *data, SbBool flag)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- // check if it is the headlight
- if (data == headlightData)
- setHeadlight( flag );
- else {
- if ( flag )
- SWITCH_LIGHT_ON(data->lightSwitch);
- else
- SWITCH_LIGHT_OFF(data->lightSwitch);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // "Edit" light menu entry callback.
- //
- // Use: static private
- //
- void
- SoSceneViewer::editLightToggleCB(Widget toggle, SvLightData *data, void *)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- data->classPt->editLight( data, XmToggleButtonGetState(toggle) );
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Attach/detach the correct manipulator on the given light.
- //
- // Use: private
- //
- void
- SoSceneViewer::editLight(SvLightData *data, SbBool flag)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- // ??? check if this is for the headlight, which is special cased
- // ??? since a manipulator cannot be used (aligned to camera).
- SbBool forHeadlight = (data == data->classPt->headlightData);
-
- //
- // attach the manip to the light and add it to the scene
- //
- if (flag) {
-
- // allocate the right manipulator type if needed
- if (!forHeadlight && data->manip == NULL) {
- switch (data->type) {
- case SoLight::DIRECTIONAL:
- {
- data->manip = new SoDirectionalLightManip;
-
- // make the manip come at some meaningfull position based
- // on the current camera view volume. This position should
- // match whatever is done when the other lights are created.
- SbViewVolume vv;
- camera->getViewVolume(vv);
- SbVec3f forward = - vv.zVector();
- SbVec3f position( vv.ulf + forward * vv.nearToFar * .25 );
- SoTransform *xfm = data->manip->getWorkSpaceOffset();
- xfm->translation = position;
- }
- break;
- case SoLight::POINT:
- data->manip = new SoPointLightManip;
- break;
- case SoLight::SPOT:
- data->manip = new SoSpotLightManip;
- break;
- }
- data->manip->ref();
- }
- else if (forHeadlight && headlightEditor == NULL) {
- headlightEditor = new SoXtDirectionalLightEditor;
- headlightEditor->setTitle("Headlight Editor");
- }
-
- // if this is for the headlight, make sure we have the
- // current viewer headlight
- if (forHeadlight)
- data->light = data->classPt->getHeadlight();
-
- // get the path from the root to the light node
- SoSearchAction sa;
- sa.setNode( data->light );
- sa.apply( currentViewer->getSceneGraph() );
- SoPath *path = sa.getPath();
- // ??? light is probably turned off so we don't
- // ??? need to print a warning message. Just don't
- // ??? do anything
- if (path == NULL)
- return;
-
- if (forHeadlight) {
- // attach the dir light editor
- // ??? don't use the path from the root to the headlight
- // ??? since we want the light to be relative to the
- // ??? camera (i.e. moving the camera shouldn't affect
- // ??? the arrow in the editor since that direction
- // ??? is relative to the camera).
- SoPath *littlePath = new SoPath( data->light );
- headlightEditor->attach( littlePath );
- headlightEditor->show();
- }
- else {
- // attach manip and insert it in the scene
- data->manip->attach( path );
-
- // After attaching, we set the workspace and edit paths to
- // be just single node paths containing the light.
- // We want to do this so that changing the camera and the
- // headlight rotation will not cause notification triggers on the
- // edit and work space paths. This will make it more efficient.
- // We can do this ONLY because we know the structure of our
- // scene graph. The scene graph is designed so that no transforms
- // affect the light (i.e., no transforms that affect the light
- // appear between traversing the camera and traversing the light).
- // We can't just attach to this littlePath in the first place,
- // because the "attach()" method creates a default size for
- // light manipulators based on the size of the
- // scene given by the path handed to attach().
-
- // So we attach to the full path, which establishes a nice size,
- // and then we set the other two paths to be more efficient.
- SoPath *littlePath = new SoPath( data->light );
- data->manip->setWorkSpacePath( littlePath );
- data->manip->setEditPath( littlePath );
-
- // add the manip to the scene graph
- if (selection->findChild(data->manip) < 0)
- selection->addChild( data->manip );
-
- // now that the light manip has been attached, make sure
- // that they all have consistent sizes (they come up to be
- // a percentage of the scene size, which will change over
- // time, so light 1 and light 2 will not otherwise have the
- // same size).
- if ( calculatedLightManipSize )
- data->manip->setSizingBox( lightManipSize );
- else {
- // get the size of the first light manip. Others will
- // use that size....
- lightManipSize = data->manip->getSizingBox();
- calculatedLightManipSize = TRUE;
- }
- }
- }
- //
- // detach the manip from the light and remove it from the scene
- //
- else {
- if (forHeadlight) {
- // detach editor from light
- if (headlightEditor != NULL) {
- headlightEditor->detach();
- headlightEditor->hide();
- }
- }
- else {
- // detach manip from light
- if (data->manip != NULL) {
- data->manip->detach();
- selection->removeChild( data->manip );
- }
- }
- }
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Called by "Edit Color" light menu entry.
- //
- // Use: static private
- //
- void
- SoSceneViewer::editLightColorCB(Widget, SvLightData *data, void *)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- // create the color editor with the right title
- if (data->colorEditor == NULL) {
- data->colorEditor = new SoXtColorEditor;
- char str[50];
- strcpy(str, data->name);
- strcat(str, " Light Color");
- data->colorEditor->setTitle(str);
- }
-
- if ( !data->colorEditor->isAttached() ) {
- // if this is for the headlight, make sure we have the
- // current viewer headlight
- if (data == data->classPt->headlightData)
- data->light = data->classPt->getHeadlight();
-
- // normalize the light intensity
- SbColor col;
- col = data->light->color.getValue();
- col *= data->light->intensity.getValue();
- data->light->intensity.setValue( 1.0 );
- data->light->color.setValue( col );
-
- data->colorEditor->attach( &data->light->color, data->light );
- }
-
- data->colorEditor->show();
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // remove button menu entry callback.
- //
- // Use: static private
- //
- void
- SoSceneViewer::removeLightCB(Widget, SvLightData *data, void *)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- data->classPt->removeLight(data);
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // removes the light from the scene, and removes the light data
- // and pulldown menu entry.
- //
- // Use: private
- //
- void
- SoSceneViewer::removeLight(SvLightData *data)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- // delete the color editor and manip
- delete data->colorEditor;
- if (data->manip != NULL) {
- data->manip->detach();
- int index = selection->findChild(data->manip);
- if (index > 0)
- selection->removeChild(index);
- data->manip->unref();
- }
-
- // remove the light from the scene
- lightGroup->removeChild( data->lightSwitch );
-
- // nuke the menu entry
- if (data->cascadeWidget != NULL)
- XtDestroyWidget( data->cascadeWidget );
-
- // remove from list and delete the struct
- lightDataList.remove( lightDataList.find(data) );
- delete data;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Called whenever a light submenu is mapped on screen (update
- // the toggles)
- //
- // Use: static private
- //
- void
- SoSceneViewer::lightSubmenuDisplay(Widget, SvLightData *data, void *)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoSceneViewer *sv = data->classPt;
- SbBool set;
-
- //
- // update the "on/off" toggle
- //
- if (data == sv->headlightData)
- set = sv->isHeadlight();
- else
- set = IS_LIGHT_ON(data->lightSwitch);
- if (set)
- TOGGLE_ON(data->onOffWidget);
- else
- TOGGLE_OFF(data->onOffWidget);
-
- //
- // update the "Edit" toggle
- //
- if (data == sv->headlightData)
- set = (sv->headlightEditor != NULL && sv->headlightEditor->isVisible());
- else
- set = (data->manip != NULL && data->manip->isAttached());
- if (set)
- TOGGLE_ON(data->iconWidget);
- else
- TOGGLE_OFF(data->iconWidget);
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Called after a paste operation has completed.
- //
- // Use: static, private
- //
- void
- SoSceneViewer::pasteDoneCB(void *userData, SoPathList *pathList)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoSceneViewer *sv = (SoSceneViewer *) userData;
- sv->pasteDone(pathList);
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Called after a paste operation has completed, this adds the
- // pasted data to our scene graph.
- //
- // Use: private
- //
- void
- SoSceneViewer::pasteDone(SoPathList *pathList)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- if (pathList->length() <= 0)
- return;
-
- // first, detach manips from all selected objects
- detachManipFromAll();
-
- // now, turn off the sel/desel callbacks.
- // we'll turn them on again after we've adjusted the selection
- selection->removeObjectSelectedCallback( SoSceneViewer::selectionCallback, this );
- selection->removeObjectDeselectedCallback( SoSceneViewer::deselectionCallback, this );
-
- // now deselect all, and build up a selection from the pasted paths
- selection->deselectAll();
-
- // Add every path in the path list as a child under selection.
- // Then select each of these paths.
- for (int i = 0; i < pathList->length(); i++) {
-
- // if the head of the path is a selection node, then don't
- // paste the head - rather, paste all of its children.
- // this makes sure we don't have more than 1 selection node.
- // While we're adding the paths as children, select each path.
- SoPath *p = (*pathList)[i];
- SoNode *head = p->getHead();
- SoPath *selpath;
- if (head->isOfType(SoSelection::getClassTypeId())) {
- for (int j = 0; j < ((SoSelection *)head)->getNumChildren(); j++) {
- selection->addChild(((SoSelection *)head)->getChild(j));
-
- // create a path from selection to this child
- // and select the path.
- selpath = new SoPath(selection);
- selpath->append(selection->getNumChildren() - 1);
- selection->select(selpath);
- }
- }
- else {
- // not a selection node, so just add it.
- selection->addChild(p->getHead());
-
- // create a path from selection to this child
- // and select the path.
- selpath = new SoPath(selection);
- selpath->append(selection->getNumChildren() - 1);
- selection->select(selpath);
- }
- }
-
- // now add manips to all the selected objects
- attachManipToAll(curManip);
-
- // and turn the sel/desel callbacks back on
- selection->addObjectSelectedCallback( SoSceneViewer::selectionCallback, this );
- selection->addObjectDeselectedCallback( SoSceneViewer::deselectionCallback, this );
-
- // enable/disable keyboard shortcuts
- updateCommandAvailability();
-
- delete pathList;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Build routine for SceneViewer. This creates all of the X widgets
- //
- // Use: public, virtual
-
- Widget
- SoSceneViewer::buildWidget(Widget parent, const char *name)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- int n;
- Arg args[10];
-
- // create a form to hold everything together
- SbVec2s size = getSize();
- n = 0;
- if (size[0] != 0 && size[1] != 0) {
- XtSetArg(args[n], XtNwidth, size[0]); n++;
- XtSetArg(args[n], XtNheight, size[1]); n++;
- }
- mgrWidget = XtCreateWidget(name, xmFormWidgetClass, parent, args, n);
- registerWidget(mgrWidget, "SoSceneViewer");
-
- // create the topbar menu
- if (showMenuFlag)
- buildAndLayoutMenu(mgrWidget);
-
- // build and layout the current viewer
- buildAndLayoutViewer(currentViewer);
-
- // manage those children
- if (showMenuFlag)
- XtManageChild(menuWidget);
- currentViewer->show();
-
- // get the highlight style (line or bbox) from X resources
- SoXtResource xr(mgrWidget);
- char *style;
- if (xr.getResource("highlightStyle", "HighlightStyle", style)) {
- if (strcmp(style, "line") == 0)
- selection->setHighlightStyle(lineHighlight);
- else if (strcmp(style, "box") == 0)
- selection->setHighlightStyle(boxHighlight);
- }
-
- // clipboard is for copy/paste of 3d data.
- //??? what if this SceneViewer had its widget destroyed and rebuilt?
- //??? we need to destroy the clipboards when that happens.
- clipboard = new SoXtClipboard(mgrWidget);
-
- return mgrWidget;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Builds and layout the given viewer.
- //
- // Use: private
- void
- SoSceneViewer::buildAndLayoutViewer(SoXtFullViewer *vwr)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- if (mgrWidget == NULL)
- return;
-
- // build the viewer if necessary
- if (vwr->getWidget() == NULL)
- vwr->build(mgrWidget);
-
- // layout the viewer to be attached under the topbar menu
- // (if the pulldown menu is shown)
- Arg args[12];
- int n = 0;
- if ( showMenuFlag ) {
- XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
- XtSetArg(args[n], XmNtopWidget, menuWidget); n++;
- }
- else {
- XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
- }
- XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
- XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
- XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
- XtSetValues(vwr->getWidget(), args, n);
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Create topbar menu. Invalid buttons are rendered gray.
- // Each button's callback include a structure with the ID
- // of the button and a pointer to the SoSceneViewer that created
- // it.
- //
- // Use: private
- //
- void
- SoSceneViewer::buildAndLayoutMenu(Widget parent)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- if (menuWidget != NULL)
- return;
-
- Arg args[4];
- int i, j, n, id;
- WidgetList buttons, subButtons;
- int itemCount, subItemCount;
- WidgetClass widgetClass;
- String callbackReason;
-
- // create topbar menu
- menuWidget = XmCreateMenuBar(parent, "menuBar", NULL, 0);
-
- itemCount = XtNumber(pulldownData);
- buttons = (WidgetList) XtMalloc(itemCount * sizeof(Widget));
-
- for (i = 0; i < itemCount; i++) {
- // Make Topbar menu button
- Widget subMenu = XmCreatePulldownMenu(menuWidget, NULL, NULL, 0);
-
- id = pulldownData[i].id;
- menuItems[id].widget = subMenu;
- XtAddCallback(subMenu, XmNmapCallback,
- (XtCallbackProc) SoSceneViewer::menuDisplay,
- (XtPointer) &menuItems[id]);
-
- XtSetArg(args[0], XmNsubMenuId, subMenu);
- buttons[i] = XtCreateWidget(pulldownData[i].name,
- xmCascadeButtonGadgetClass, menuWidget, args, 1);
-
- // Make subMenu buttons
- subItemCount = pulldownData[i].subItemCount;
- subButtons = (WidgetList) XtMalloc(subItemCount * sizeof(Widget));
-
- for (j = 0; j < subItemCount; j++) {
- if (pulldownData[i].subMenu[j].id == SV_SEPARATOR)
- subButtons[j] = XtCreateWidget(NULL, xmSeparatorGadgetClass,
- subMenu, NULL, 0);
- else {
- switch (pulldownData[i].subMenu[j].buttonType) {
- case SV_PUSH_BUTTON:
- widgetClass = xmPushButtonGadgetClass;
- callbackReason = XmNactivateCallback;
- n = 0;
- break;
- case SV_TOGGLE_BUTTON:
- widgetClass = xmToggleButtonGadgetClass;
- callbackReason = XmNvalueChangedCallback;
- n = 0;
- break;
- case SV_RADIO_BUTTON:
- widgetClass = xmToggleButtonGadgetClass;
- callbackReason = XmNvalueChangedCallback;
- XtSetArg(args[0], XmNindicatorType, XmONE_OF_MANY);
- n = 1;
- break;
- default:
- fprintf(stderr, "SceneViewer INTERNAL ERROR: bad buttonType\n");
- break;
- }
-
- // check for keyboard accelerator
- char *accel = pulldownData[i].subMenu[j].accelerator;
- char *accelText = pulldownData[i].subMenu[j].accelText;
- if (accel != NULL) {
- XtSetArg(args[n], XmNaccelerator, accel); n++;
-
- if (accelText != NULL) {
- XmString xmstr = XmStringCreate(accelText,
- XmSTRING_DEFAULT_CHARSET);
- XtSetArg(args[n], XmNacceleratorText, xmstr); n++;
- //??? can we ever free the xmstr?
- }
- }
-
- subButtons[j] = XtCreateWidget(
- pulldownData[i].subMenu[j].name,
- widgetClass,
- subMenu, args, n);
-
- id = pulldownData[i].subMenu[j].id;
- menuItems[id].widget = subButtons[j];
- XtAddCallback(subButtons[j], callbackReason,
- (XtCallbackProc)SoSceneViewer::processTopbarEvent,
- (XtPointer) &menuItems[id]);
- }
- }
- XtManageChildren(subButtons, subItemCount);
- XtFree((char *)subButtons);
- }
- XtManageChildren(buttons, itemCount);
- XtFree((char *)buttons);
-
- //
- // layout the menu bar
- //
- n = 0;
- XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
- XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
- XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
- XtSetValues(menuWidget, args, n);
-
- //
- // If no accumulation buffer, disable antialiasing button.
- // If no fog support, disable fog button.
- //
- if ( getgdesc( GD_BITS_ACBUF_HW ) == 0 ) {
- XtSetArg(args[0], XmNsensitive, False);
- XtSetValues(menuItems[SV_VIEW_ANTIALIASING].widget, args, 1);
- }
- if ( getgdesc( GD_FOGVERTEX ) == 0 ) {
- XtSetArg(args[0], XmNsensitive, False);
- XtSetValues(menuItems[SV_VIEW_FOG].widget, args, 1);
- }
-
-
- //
- // Add the light items which are dynamically created
- //
-
- // first add the headlight
- addLightMenuEntry(headlightData);
- XtUnmanageChild(headlightData->removeWidget);
- XtUnmanageChild(headlightData->editColorWidget);
- XmString xmstr = XmStringCreate("Edit", XmSTRING_DEFAULT_CHARSET);
- XtSetArg(args[0], XmNlabelString, xmstr);
- XtSetValues(headlightData->iconWidget, args, 1);
-
- // now the regular lights
- for (i=0; i < lightDataList.length(); i++)
- addLightMenuEntry( (SvLightData *) lightDataList[i] );
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Show/hide the pulldown menu bar.
- //
- // Use: public
- void
- SoSceneViewer::showMenu(SbBool flag)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- if (showMenuFlag == flag || mgrWidget == NULL) {
- showMenuFlag = flag;
- return;
- }
-
- showMenuFlag = flag;
-
- if ( showMenuFlag ) {
-
- // turn topbar menu on
- if (menuWidget == NULL)
- buildAndLayoutMenu(mgrWidget);
- XtManageChild(menuWidget);
-
- // attach viewer to bottom of menu
- Arg args[2];
- int n = 0;
- XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
- XtSetArg(args[n], XmNtopWidget, menuWidget); n++;
- XtSetValues(currentViewer->getWidget(), args, n);
- }
- else {
- // attach viewer to form
- Arg args[2];
- int n = 0;
- XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
- XtSetValues(currentViewer->getWidget(), args, n);
-
- // turn topbar menu off
- if (menuWidget != NULL)
- XtUnmanageChild(menuWidget);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Manage the changes in the selected node(s)
- //
- // Use: private, static
- //
- void
- SoSceneViewer::deselectionCallback( void *userData, // my data
- SoPath *deselectedObject ) // object
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoSceneViewer *sv = (SoSceneViewer *) userData;
-
- // remove the manip
- sv->detachManip( deselectedObject );
-
- // Remove editors
- if (sv->materialEditor)
- sv->materialEditor->detach();
-
- if (sv->colorEditor)
- sv->colorEditor->detach();
-
- if (sv->transformSliderSet)
- sv->transformSliderSet->setNode( NULL ); // ??? same as detach ??? rc
-
- // enable/disable cmd key shortcuts and menu items
- sv->updateCommandAvailability();
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Manage the changes in the selected node(s)
- //
- // Use: private, static
- //
- void
- SoSceneViewer::selectionCallback( void *userData, // my data
- SoPath *selectedObject ) // object
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoSceneViewer *sv = (SoSceneViewer *) userData;
-
- // attach the manip
- sv->attachManip( sv->curManip, selectedObject );
-
- //
- // If active, attach editors to new selection.
- //
- SoMaterial *mtl = NULL;
- if ( sv->materialEditor && (sv->materialEditor->getWidget() != NULL)) {
- mtl = sv->findMaterialForAttach(selectedObject);
- sv->materialEditor->attach(mtl);
- }
-
- if (sv->colorEditor && (sv->colorEditor->getWidget() != NULL)) {
- if (mtl == NULL)
- mtl = sv->findMaterialForAttach(selectedObject);
- sv->colorEditor->attach(&(mtl->diffuseColor), 0, mtl);
- }
-
- if ( sv->transformSliderSet && sv->transformSliderSet->getWidget() ) {
- SoPath *editTransformPath;
- editTransformPath = sv->findTransformForAttach( selectedObject );
- if ( editTransformPath == NULL ) {
- sv->transformSliderSet->setNode( NULL );
- }
- else {
- sv->transformSliderSet->setNode( editTransformPath->getTail() );
- }
- }
-
- // enable/disable cmd key shortcuts and menu items
- sv->updateCommandAvailability();
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Change the highlight color by putting up a color editor.
- //
- // Use: private
- //
- void
- SoSceneViewer::editHighlightColor()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- if (highlightColorEditor == NULL) {
- highlightColorEditor = new SoXtColorEditor;
- highlightColorEditor->setTitle("Highlight Color");
- highlightColorEditor->addColorChangedCallback(
- SoSceneViewer::highlightColorCallback, this);
- }
- highlightColorEditor->build();
-
- // set the color. our highlights are all the same color, so just pick one.
- // (although, if the user set different colors in their X defaults...)
- ignoreCallback = TRUE;
- if (selection->getHighlightStyle() == lineHighlight)
- highlightColorEditor->setColor(lineHighlight->getColor());
- else
- highlightColorEditor->setColor(boxHighlight->getColor());
- ignoreCallback = FALSE;
-
- // show that color editor!
- highlightColorEditor->show();
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Callback proc invoked by the color editor, this changes the
- // highlight color for selected objects.
- //
- // Use: static, private
- //
- void
- SoSceneViewer::highlightColorCallback(void *userData, const SbColor *c)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoSceneViewer *sv = (SoSceneViewer *) userData;
-
- if (sv->ignoreCallback)
- return;
-
- // change highlight color for line and box highlight styles.
- sv->boxHighlight->setColor(*c);
- sv->lineHighlight->setColor(*c);
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // This enables/disables cmd key shortcuts and menu items
- // based on whether there are any objects, and/or any selected objects
- // in the scene graph.
- //
- // Use: static private
- //
- //
- void
- SoSceneViewer::updateCommandAvailability()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- Arg args[1];
-
- // enable/disable based on the number of child objects in scene
- if (selection->getNumChildren() == 0)
- XtSetArg(args[0], XmNsensitive, False);
- else XtSetArg(args[0], XmNsensitive, True);
-
- // save (if no children, nothing to save)
- XtSetValues(menuItems[SV_FILE_SAVE].widget, args, 1);
- XtSetValues(menuItems[SV_FILE_SAVE_AS].widget, args, 1);
-
- #ifndef EXPLORER
- // pickAll (if no children, nothing to pick)
- XtSetValues(menuItems[SV_EDIT_PICK_ALL].widget, args, 1);
- #endif
-
-
- // enable/disable based on the number of selected objects
- if (selection->getNumSelected() == 0)
- XtSetArg(args[0], XmNsensitive, False);
- else XtSetArg(args[0], XmNsensitive, True);
-
- // if nothing selected, then cannot pick parent, cut, copy, delete,
- // view selection, bring up editors
- #ifndef EXPLORER
- XtSetValues(menuItems[SV_EDIT_PICK_PARENT].widget, args, 1);
- XtSetValues(menuItems[SV_EDIT_CUT].widget, args, 1);
- XtSetValues(menuItems[SV_EDIT_COPY].widget, args, 1);
- XtSetValues(menuItems[SV_EDIT_DELETE].widget, args, 1);
- #endif
- XtSetValues(menuItems[SV_VIEW_SELECTION].widget, args, 1);
- XtSetValues(menuItems[SV_EDITOR_TRANSFORM].widget, args, 1);
- XtSetValues(menuItems[SV_EDITOR_MATERIAL].widget, args, 1);
- XtSetValues(menuItems[SV_EDITOR_COLOR].widget, args, 1);
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Called by Xt when a menu is about to be displayed.
- // This gives us a chance to update any items in the menu.
- //
- // Use: static private
- //
- void
- SoSceneViewer::menuDisplay(Widget, SoSceneViewerData *data, XtPointer)
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoSceneViewer *sv = data->classPt;
- Arg args[1];
- char str[100];
- XmString xmstr;
-
- switch (data->id) {
- case SV_FILE:
- // disable saving if there isn't any geometry
- if (sv->selection->getNumChildren() == 0)
- XtSetArg(args[0], XmNsensitive, False);
- else
- XtSetArg(args[0], XmNsensitive, True);
-
- XtSetValues(sv->menuItems[SV_FILE_SAVE].widget, args, 1);
- XtSetValues(sv->menuItems[SV_FILE_SAVE_AS].widget, args, 1);
-
- // update the "Save" menu entry to reflect the current file name
- strcpy(str, "Save");
- if (sv->fileName != NULL) {
- // get the file name withought the entire path
- char *pt = strrchr(sv->fileName, '/'); // last occurance of '/'
- pt = (pt == NULL) ? sv->fileName : pt + 1;
- strcat(str, " -> ");
- strcat(str, pt);
- }
- xmstr = XmStringCreate(str, XmSTRING_DEFAULT_CHARSET);
- XtSetArg(args[0], XmNlabelString, xmstr);
- XtSetValues(sv->menuItems[SV_FILE_SAVE].widget, args, 1);
- //??? can we ever free the xmstr?
- break;
-
- #ifndef EXPLORER
- case SV_EDIT:
- // disable cut, copy, delete, pickParent if there is no selection
- if(sv->selection->getNumSelected() == 0)
- XtSetArg(args[0], XmNsensitive, False);
- else
- XtSetArg(args[0], XmNsensitive, True);
-
- XtSetValues(sv->menuItems[SV_EDIT_PICK_PARENT].widget, args, 1);
- XtSetValues(sv->menuItems[SV_EDIT_CUT].widget, args, 1);
- XtSetValues(sv->menuItems[SV_EDIT_COPY].widget, args, 1);
- XtSetValues(sv->menuItems[SV_EDIT_DELETE].widget, args, 1);
-
- // disable pick all if there are nothing to pick
- if (sv->selection->getNumChildren() == 0)
- XtSetArg(args[0], XmNsensitive, False);
- else
- XtSetArg(args[0], XmNsensitive, True);
- XtSetValues(sv->menuItems[SV_EDIT_PICK_ALL].widget, args, 1);
- break;
- #endif /* EXPLORER */
-
- case SV_VIEW:
- // set pick/edit toggle
- if ( sv->isViewing() )
- TOGGLE_OFF(sv->menuItems[SV_VIEW_PICK].widget);
- else TOGGLE_ON(sv->menuItems[SV_VIEW_PICK].widget);
-
- #ifdef EXPLORER
- // set user pick toggle
- if ( sv->userModeFlag )
- TOGGLE_ON(sv->menuItems[SV_VIEW_USER].widget);
- else TOGGLE_OFF(sv->menuItems[SV_VIEW_USER].widget);
- #endif
- // Set the correct viewer
- TOGGLE_OFF(sv->menuItems[SV_VIEW_EXAMINER].widget);
- TOGGLE_OFF(sv->menuItems[SV_VIEW_WALK].widget);
- TOGGLE_OFF(sv->menuItems[SV_VIEW_PLANE].widget);
- TOGGLE_OFF(sv->menuItems[SV_VIEW_FLY].widget);
- switch ( sv->whichViewer ) {
- case SV_VWR_EXAMINER:
- TOGGLE_ON(sv->menuItems[SV_VIEW_EXAMINER].widget);
- break;
- case SV_VWR_WALK:
- TOGGLE_ON(sv->menuItems[SV_VIEW_WALK].widget);
- break;
- case SV_VWR_FLY:
- TOGGLE_ON(sv->menuItems[SV_VIEW_FLY].widget);
- break;
- case SV_VWR_PLANE:
- TOGGLE_ON(sv->menuItems[SV_VIEW_PLANE].widget);
- break;
- }
-
- // set the correct transparency type
- TOGGLE_OFF(sv->menuItems[SV_VIEW_SCREEN_TRANSPARENCY].widget);
- TOGGLE_OFF(sv->menuItems[SV_VIEW_BLEND_TRANSPARENCY].widget);
- TOGGLE_OFF(sv->menuItems[SV_VIEW_DELAY_BLEND_TRANSPARENCY].widget);
- TOGGLE_OFF(sv->menuItems[SV_VIEW_SORT_BLEND_TRANSPARENCY].widget);
- switch( sv->getTransparencyType() ) {
- case SoGLRenderAction::SCREEN_DOOR:
- TOGGLE_ON(sv->menuItems[SV_VIEW_SCREEN_TRANSPARENCY].widget);
- break;
- case SoGLRenderAction::BLEND:
- TOGGLE_ON(sv->menuItems[SV_VIEW_BLEND_TRANSPARENCY].widget);
- break;
- case SoGLRenderAction::DELAYED_BLEND:
- TOGGLE_ON(sv->menuItems[SV_VIEW_DELAY_BLEND_TRANSPARENCY].widget);
- break;
- case SoGLRenderAction::SORTED_OBJECT_BLEND:
- TOGGLE_ON(sv->menuItems[SV_VIEW_SORT_BLEND_TRANSPARENCY].widget);
- break;
- }
-
- // disable view selection if nothing is selected
- if ( sv->selection->getNumSelected() == 0 )
- XtSetArg(args[0], XmNsensitive, False);
- else
- XtSetArg(args[0], XmNsensitive, True);
- XtSetValues(sv->menuItems[SV_VIEW_SELECTION].widget, args, 1);
-
- // set fog toggle
- if ( sv->fogFlag )
- TOGGLE_ON(sv->menuItems[SV_VIEW_FOG].widget);
- else TOGGLE_OFF(sv->menuItems[SV_VIEW_FOG].widget);
-
- // set antialiasing toggle
- if ( sv->antialiasingFlag )
- TOGGLE_ON(sv->menuItems[SV_VIEW_ANTIALIASING].widget);
- else TOGGLE_OFF(sv->menuItems[SV_VIEW_ANTIALIASING].widget);
-
- break;
-
- #ifndef EXPLORER
- case SV_SELECTION:
- // mirror the selection policy
- TOGGLE_OFF(sv->menuItems[SV_SEL_SINGLE_SELECT].widget);
- TOGGLE_OFF(sv->menuItems[SV_SEL_TOGGLE_SELECT].widget);
- TOGGLE_OFF(sv->menuItems[SV_SEL_SHIFT_SELECT].widget);
- switch ( sv->selection->getSelectionPolicy() ) {
- case SoSelection::SINGLE:
- TOGGLE_ON (sv->menuItems[SV_SEL_SINGLE_SELECT].widget);
- break;
- case SoSelection::TOGGLE:
- TOGGLE_ON (sv->menuItems[SV_SEL_TOGGLE_SELECT].widget);
- break;
- case SoSelection::SHIFT:
- TOGGLE_ON (sv->menuItems[SV_SEL_SHIFT_SELECT].widget);
- break;
- case SoSelection::CUSTOM:
- default:
- fprintf(stderr, "INTERNAL ERROR, unknown selection policy\n");
- break;
- }
-
- // and the highlight style
- TOGGLE_OFF(sv->menuItems[SV_SEL_LINE_HIGHLIGHT].widget);
- TOGGLE_OFF(sv->menuItems[SV_SEL_BBOX_HIGHLIGHT].widget);
- TOGGLE_OFF(sv->menuItems[SV_SEL_NO_HIGHLIGHT].widget);
- if (sv->selection->getHighlightStyle() == sv->lineHighlight)
- TOGGLE_ON (sv->menuItems[SV_SEL_LINE_HIGHLIGHT].widget);
- else if (sv->selection->getHighlightStyle() == sv->boxHighlight)
- TOGGLE_ON (sv->menuItems[SV_SEL_BBOX_HIGHLIGHT].widget);
- else // (sv->selection->getHighlightStyle() == NULL)
- TOGGLE_ON(sv->menuItems[SV_SEL_NO_HIGHLIGHT].widget);
- break;
- #endif /* EXPLORER */
-
- case SV_EDITOR:
- // disable items if there is no selection
- if(sv->selection->getNumSelected() == 0)
- XtSetArg(args[0], XmNsensitive, False);
- else
- XtSetArg(args[0], XmNsensitive, True);
-
- XtSetValues(sv->menuItems[SV_EDITOR_TRANSFORM].widget, args, 1);
- XtSetValues(sv->menuItems[SV_EDITOR_MATERIAL].widget, args, 1);
- XtSetValues(sv->menuItems[SV_EDITOR_COLOR].widget, args, 1);
- break;
-
- case SV_MANIP:
-
- // First, the section with the different types of manipulators.
- TOGGLE_OFF( sv->menuItems[SV_MANIP_HANDLEBOX].widget );
- TOGGLE_OFF( sv->menuItems[SV_MANIP_TRACKBALL].widget );
- TOGGLE_OFF( sv->menuItems[SV_MANIP_JACK].widget );
- TOGGLE_OFF( sv->menuItems[SV_MANIP_XFBOX].widget );
- TOGGLE_OFF( sv->menuItems[SV_MANIP_DRAGPOINT].widget );
- TOGGLE_OFF( sv->menuItems[SV_MANIP_NONE].widget );
-
- // Turn appropriate radio button on
- if (sv->curManip == SV_HANDLEBOX)
- TOGGLE_ON(sv->menuItems[SV_MANIP_HANDLEBOX].widget);
- else if (sv->curManip == SV_TRACKBALL)
- TOGGLE_ON(sv->menuItems[SV_MANIP_TRACKBALL].widget);
- else if (sv->curManip == SV_JACK)
- TOGGLE_ON(sv->menuItems[SV_MANIP_JACK].widget);
- else if (sv->curManip == SV_XFBOX)
- TOGGLE_ON(sv->menuItems[SV_MANIP_XFBOX].widget);
- else if (sv->curManip == SV_DRAGPOINT)
- TOGGLE_ON(sv->menuItems[SV_MANIP_DRAGPOINT].widget);
- else
- TOGGLE_ON(sv->menuItems[SV_MANIP_NONE].widget);
-
- // Next, the toggle that says whether we replace current
- // manipulators every time we change the type given in the menu.
- if (sv->curManipReplaces == TRUE )
- TOGGLE_ON( sv->menuItems[SV_MANIP_REPLACE_ALL].widget );
- else
- TOGGLE_OFF( sv->menuItems[SV_MANIP_REPLACE_ALL].widget );
-
- break;
-
- case SV_LIGHT:
- // disable the add light entries if we have more than 8 lights
- if (sv->lightDataList.length() < 8)
- XtSetArg(args[0], XmNsensitive, True);
- else
- XtSetArg(args[0], XmNsensitive, False);
-
- XtSetValues(sv->menuItems[SV_LIGHT_ADD_DIRECT].widget, args, 1);
- XtSetValues(sv->menuItems[SV_LIGHT_ADD_POINT].widget, args, 1);
- XtSetValues(sv->menuItems[SV_LIGHT_ADD_SPOT].widget, args, 1);
-
- // update the headlight label (show on/off with '*')
- sv->isHeadlight() ? strcpy(str, "* ") : strcpy(str, " ");
- strcat(str, sv->headlightData->name);
- xmstr = XmStringCreate(str, XmSTRING_DEFAULT_CHARSET);
- XtSetArg(args[0], XmNlabelString, xmstr);
- XtSetValues(sv->headlightData->cascadeWidget, args, 1);
- //??? can we ever free the xmstr?
-
- // update the lights label (show on/off with '*')
- {
- for (int i=0; i < sv->lightDataList.length(); i++) {
- SvLightData *data = (SvLightData *) sv->lightDataList[i];
- IS_LIGHT_ON(data->lightSwitch) ? strcpy(str, "* ") : strcpy(str, " ");
- strcat(str, data->name);
- xmstr = XmStringCreate(str, XmSTRING_DEFAULT_CHARSET);
- XtSetArg(args[0], XmNlabelString, xmstr);
- XtSetValues(data->cascadeWidget, args, 1);
- //??? can we ever free the xmstr?
- }
- }
- break;
-
- default:
- break;
- }
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Determines whether a given node is affected by a transform.
- //
- // Use: static, public
- //
- SbBool
- SoSceneViewer::isAffectedByTransform(
- SoNode *theNode ) // node to be affected?
- //
- ////////////////////////////////////////////////////////////////////////
- {
- if ( theNode->isOfType( SoGroup::getClassTypeId() )
- || theNode->isOfType( SoShape::getClassTypeId() )
- || theNode->isOfType( SoCamera::getClassTypeId() )
- || theNode->isOfType( SoLight::getClassTypeId() ) ) {
- return TRUE;
- }
- return FALSE;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Determines whether a given node is affected by material node.
- //
- // Use: static, public
- //
- SbBool
- SoSceneViewer::isAffectedByMaterial(
- SoNode *theNode ) // node to be affected?
- //
- ////////////////////////////////////////////////////////////////////////
- {
- if ( theNode->isOfType( SoGroup::getClassTypeId() )
- || theNode->isOfType( SoShape::getClassTypeId() ) ) {
- return TRUE;
- }
- return FALSE;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Create the lights and camera environment structure.
- //
- // Use: private
- //
- void
- SoSceneViewer::createLightsCameraEnvironment()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- // Group {
- // Label { "SoSceneViewer Environment v3.0" }
- // Camera {}
- // Environment {}
- // Group {
- // Switch { Light 1 } # switch is child 0, light is child 0
- // Switch { Light 2 } # switch is child 1, light is child 0
- // ...
- // }
- // }
-
- lightsCameraEnvironment = new SoGroup;
- camera = new SoPerspectiveCamera;
- environment = new SoEnvironment;
- lightGroup = new SoGroup;
- envLabel = new SoLabel;
-
- envLabel->label.setValue(SV_ENV_LABEL);
- lightsCameraEnvironment->addChild(envLabel);
- lightsCameraEnvironment->addChild(camera);
- lightsCameraEnvironment->addChild(environment);
- lightsCameraEnvironment->addChild(lightGroup);
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Brings up the "About..." dialog (same code as gavin demo programs)
- //
- // Use: private
- //
- void
- SoSceneViewer::showAboutDialog()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- if (access("/usr/share/help/SceneViewer/SceneViewer.about", R_OK) != 0)
- {
- system("xconfirm -t 'Sorry, could not find "
- "/usr/share/help/SceneViewer/SceneViewer.about' > /dev/null");
- return;
- }
-
- char command[100];
- sprintf(command, "showcase -v /usr/share/help/SceneViewer/SceneViewer.about");
-
- int err = system(command);
- if (err)
- {
- system("xconfirm -t 'You must install showcase"
- " for this function to work' > /dev/null");
- return;
- }
- }
-
- #ifdef EXPLORER
- void SoSceneViewer::changeCamera(SoCamera *newCamera)
- {
- lightsCameraEnvironment->insertChild(newCamera,0);
- setCamera(newCamera);
- lightsCameraEnvironment->removeChild(camera);
- camera = newCamera;
- }
- #endif
-
- //
- // define those generic virtual functions
- //
- const char *
- SoSceneViewer::getDefaultWidgetName() const
- { return "SoSceneViewer"; }
-
- const char *
- SoSceneViewer::getDefaultTitle() const
- { return "SceneViewer"; }
-
- const char *
- SoSceneViewer::getDefaultIconTitle() const
- { return "SceneViewer"; }
- //
- // added by smf
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Broadcast the Enviroment nodes (camera and lights)
- //
- // Use: private
- SbBool
- SoSceneViewer::BroadcastEnv()
- //
- ////////////////////////////////////////////////////////////////////////
- {
-
- SoWriteAction nwa;
- int cnt;
- nwa.getOutput()->setBuffer(mybuff,1000,NULL);
- nwa.apply(envLabel);
- nwa.apply(camera);
- nwa.apply(environment);
- nwa.apply(lightGroup);
- if (isHeadlight())
- nwa.apply(getHeadlight());
-
- cnt = sendto(outfd, mybuff, strlen(mybuff), 0, &outaddr, outaddrlen);
- #ifdef MYDEBUG
- printf("sent %d bytes to network\n",cnt);
- #endif
- if (cnt < 0) {
- perror("sendto");
- }
-
- #ifdef MYDEBUG
- printf("BUFFER = %s\n",mybuff);
- #endif
- return TRUE;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Read environment data from network. We expect the following nodes:
- //
- // Group {
- // Label { "SoSceneViewer Environment v3.0" }
- // Camera {}
- // Environment {}
- // LightGroup {
- // Switch { DirectionalLight } # 1
- // ...
- // Switch { DirectionalLight } # 6
- // }
- // DirectionalLight {} # optional headlight
- // }
- //
- // Use: private
- SbBool
- SoSceneViewer::ReadBroadcastEnv()
- //
- ////////////////////////////////////////////////////////////////////////
- {
- SoInput in;
- SoNode *n;
- SoGroup *g = NULL;
- SoLabel *l = NULL;
- SbBool isValid = FALSE;
- SbBool ok = FALSE;
-
- while(!ok)
- {
- // if (! in.setBuffer(mybuff,strlen(mybuff))) {
- //// display an error dialog
- //char str[100];
- //strcpy(str, "Error Reading Broadcast: ");
- //SoXt::createSimpleErrorDialog(mgrWidget, "File Error Dialog", str);
- //return FALSE;
- //}
- in.setBuffer(mybuff,strlen(mybuff));
-
-
- if ((ok = SoDB::read(&in, n)) && n != NULL) {
- // we expect a label first
- n->ref();
- if (n->isOfType(SoLabel::getClassTypeId())) {
- l = (SoLabel *) n;
- isValid = (strcmp(l->label.getValue().getString(),
- SV_ENV_LABEL) == 0);
- }
- n->unref();
- }
- }
- // else if (!ok) {
- //display error dialog if there were reading errors
- // char str[100];
- // strcpy(str, "Error reading file: ");
- // strcat(str, filename);
- // SoXt::createSimpleErrorDialog(mgrWidget, "File Error Dialog", str);
- // return FALSE;
- // }
-
- // if ok, read the rest.
- if (isValid) {
- // Camera
- if (SoDB::read(&in, n) != FALSE && (n != NULL)) {
- n->ref();
- if (n->isOfType(SoPerspectiveCamera::getClassTypeId())) {
- // viewers need to be detached from the old camera
- // and attached to the new. both cameras must be in
- // the scene graph for this to happen smoothly.
- SoPerspectiveCamera *newCamera = (SoPerspectiveCamera *) n;
- lightsCameraEnvironment->insertChild(newCamera, 0);
- setCamera(newCamera);
- lightsCameraEnvironment->removeChild(camera);
- camera = newCamera;
- }
- n->unref();
- }
- // Environment
- if (SoDB::read(&in, n) != FALSE && (n != NULL)) {
- n->ref();
- if (n->isOfType(SoEnvironment::getClassTypeId())) {
- lightsCameraEnvironment->replaceChild(environment, n);
- environment = (SoEnvironment *) n;
- }
- n->unref();
- }
- // Light group
- if (SoDB::read(&in, n) != FALSE && (n != NULL)) {
- n->ref();
- if (n->isOfType(SoGroup::getClassTypeId())) {
-
- // remove all of the existing lights
- for (int i = lightDataList.length(); i > 0; i--)
- removeLight( (SvLightData *) lightDataList[i-1] );
-
- lightsCameraEnvironment->replaceChild(lightGroup, n);
- lightGroup = (SoGroup *) n;
-
- // now create a light entry for each new light
- for (i=0; i < lightGroup->getNumChildren(); i++) {
- SoNode *node = lightGroup->getChild(i);
- if (node->isOfType(SoSwitch::getClassTypeId())) {
- SoSwitch *sw = (SoSwitch *) node;
- node = sw->getChild(0);
- if (node->isOfType(SoLight::getClassTypeId()))
- addLightEntry((SoLight *)node, sw);
- }
- }
- }
- n->unref();
- }
- // Headlight (optional) - if not there, turn headlight off
- if (SoDB::read(&in, n) != FALSE && (n != NULL)) {
- n->ref();
- if (n->isOfType(SoDirectionalLight::getClassTypeId())) {
- SoDirectionalLight *headlight = getHeadlight();
- SoDirectionalLight *newLight = (SoDirectionalLight *) n;
- headlight->intensity.setValue(newLight->intensity.getValue());
- headlight->color.setValue(newLight->color.getValue());
- headlight->direction.setValue(newLight->direction.getValue());
- setHeadlight(TRUE);
- }
- n->unref();
- }
- else setHeadlight(FALSE);
- }
- else {
- fprintf(stderr, "Sorry, file is not formatted correctly\n");
- }
-
- return TRUE;
- }
-
- int readnet()
- {
- int cnt=1;
- int flag = 0 ;
-
- while(cnt > 0)
- {
- cnt = recvfrom(infd, temp, sizeof(temp), 0, &inaddr, &inaddrlen);
- if(cnt > 0)
- {
- bcopy(temp,mybuff,1000);
- flag=1;
- }
- }
- if (! flag) {
- return(0);
- }
- if(!strncmp(mybuff,"#Inventor V1.0 ascii",20))return(ENVIRONMENT);
- }
-
- // added by smf
- // called by start camera callback
- void mystartcallback(void *tmp,SoXtViewer *)
- {
- #ifdef MYDEBUG
- printf("START Camera, rotflag=1\n");
- #endif
- rotflag=1;
- }
-
- // called by finish camera callback
- void mystopcallback(void *tmp,SoXtViewer *sv)
- {
- #ifdef MYDEBUG
- printf("STOP camera,WRITE,rotflag=0\n");
- #endif
- ((SoSceneViewer *)mysv)->BroadcastEnv();
- rotflag=0;
- }
-
- // called by timer callback
- void myreadcallback(void *tmp,SoSensor *sv)
- {
- #ifdef MYDEBUG
- printf("FLAG=1,DETACH ENVIRO, READ, ATTACH ENVIRO\n");
- #endif
-
- switch (readnet())
- {
- case ENVIRONMENT:
- flag=1;
- if(envirosensor->getNumAttachments()) envirosensor->detach(mysv->lightsCameraEnvironment);
- if(! rotflag ){
- ((SoSceneViewer *)mysv)->ReadBroadcastEnv();
- }
- envirosensor->attach(mysv->lightsCameraEnvironment);
- break;
-
- default:
- break;
- }
- }
-
- // called by datasensor callback
- void mywritecallback(void *tmp,SoSensor *sv)
- {
- if(flag)
- {
- #ifdef MYDEBUG
- printf("FLAG=0\n");
- #endif
- flag=0;
- }
- else
- {
- #ifdef MYDEBUG
- printf("TIMER OFF, DETACH ENVIRO, WRITE, ATTACH ENVIRO, TIMER %d\n",timerflag);
- #endif
- timersensor->unschedule();
- if(envirosensor->getNumAttachments()) envirosensor->detach(mysv->lightsCameraEnvironment);
- ((SoSceneViewer *)mysv)->BroadcastEnv();
- envirosensor->attach(mysv->lightsCameraEnvironment);
- if(timerflag)timersensor->schedule(SbTime((unsigned long)DATATIME));
- }
-
- }
-
-
-